<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5772302</id><updated>2011-11-27T16:18:54.483-08:00</updated><category term='C#'/><category term='MCTS'/><category term='AX 2012'/><category term='Dynamics AX'/><category term='KB'/><category term='SQL'/><category term='Subversion'/><category term='DotNetNuke'/><category term='Source Code'/><category term='Axapta'/><category term='70-536'/><title type='text'>C# and AX Development</title><subtitle type='html'>Development and other stuff</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default?start-index=101&amp;max-results=100'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>139</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5772302.post-3558155813349982187</id><published>2011-05-02T09:12:00.000-07:00</published><updated>2011-05-02T09:16:30.486-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='AX 2012'/><title type='text'>LC Analyzer for AX</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Loncar Technologies&lt;/span&gt; has created an amazing product to improve development and analysis en AX (&lt;span style="font-style:italic;"&gt;AX4, AX2009 and now AX2012&lt;/span&gt;).  Take a look at &lt;a href="http://www.loncartechnologies.com"&gt;http://www.loncartechnologies.com&lt;/a&gt;.&lt;br&gt;&lt;br&gt;

Also, get some free stuff:  LC AOT Browser (browse the AOT filtered by a layer) and LC Project search (search for an object in all projects nodes).&lt;br&gt;&lt;br&gt;

Enjoy it !!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3558155813349982187?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.loncartechnologies.com' title='LC Analyzer for AX'/><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3558155813349982187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3558155813349982187' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3558155813349982187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3558155813349982187'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2011/05/lc-analyzer-for-ax.html' title='LC Analyzer for AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-7244334044147025233</id><published>2009-07-17T11:35:00.000-07:00</published><updated>2009-07-17T12:49:34.128-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='Source Code'/><title type='text'>Updating the caller Form/DataSource</title><content type='html'>If we need to notify events to the &lt;em&gt;caller form&lt;/em&gt; we can try this pattern:&lt;br&gt;&lt;br&gt;

In the child form, make a method named &lt;em&gt;updateCaller&lt;/em&gt; and invoke it when you want to notify the parent:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; updateCaller()
{
    Common common;
    Object dataSource;
    Object caller;
    ;

    &lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
    &lt;span class="rem"&gt;//We are notifying using the dataSource&lt;/span&gt;
    common = element.args().record();
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (common
        &amp;amp;&amp;amp; common.isFormDataSource()
        &amp;amp;&amp;amp; &lt;span class="kwrd"&gt;formDataSourceHasMethod&lt;/span&gt;(common.dataSource(), identifierstr(SomethingWasHappend)))
    {
        dataSource = common.dataSource();
        dataSource.SomethingWasHappend();
    }
    &lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;

    &lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
    &lt;span class="rem"&gt;//We are notifying using the form&lt;/span&gt;
    caller = element.args().caller();
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (caller
        &amp;amp;&amp;amp; classidget(caller) == classnum(SysSetupFormRun)
        &amp;amp;&amp;amp; &lt;span class="kwrd"&gt;formHasMethod&lt;/span&gt;(caller, identifierstr(SomethingWasHappend)))
    {
        caller.SomethingWasHappend();
    }
    &lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
}&lt;/pre&gt;&lt;br&gt;

Implement the handling method in the parent &lt;em&gt;form&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; SomethingWasHappend()
{
    ;
    info(&lt;span class="str"&gt;"Something was happend (Form)"&lt;/span&gt;);
}&lt;/pre&gt;&lt;br&gt;

Or if you prefer, in the &lt;em&gt;DataSource&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; SomethingWasHappend()
{
    ;
    info(&lt;span class="str"&gt;"Something was happend (DataSource)"&lt;/span&gt;);
}&lt;/pre&gt;&lt;br&gt;

Invoking it from a simple button inside the child form:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; clicked()
{
    super();

    element.updateCaller();
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

See a pratical sample in the form &lt;strong&gt;MarkupTrans &lt;/strong&gt; (&lt;em&gt;DataSource -&gt; method write&lt;/em&gt;).&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-7244334044147025233?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/7244334044147025233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=7244334044147025233' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7244334044147025233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7244334044147025233'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2009/07/updating-caller-formdatasource.html' title='Updating the caller Form/DataSource'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6955268887409974396</id><published>2009-06-27T10:55:00.000-07:00</published><updated>2009-06-27T11:43:37.179-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>How to delete AOT nodes by code (UtilIdElements solution)</title><content type='html'>In my old post: &lt;strong&gt;&lt;a href="http://olondono.blogspot.com/2007/12/how-to-delete-aot-objects-axaxapta.html"&gt;How to delete AOT objects (AX/Axapta)&lt;/a&gt;, &lt;/strong&gt;I have used the &lt;em&gt;TreeNode&lt;/em&gt; class. There is another useful method by using the &lt;strong&gt;UtilIdElements&lt;/strong&gt; &lt;em&gt;system table &lt;/em&gt;described in the following links:&lt;br&gt;&lt;br&gt;

- MS KB 913530 (&lt;a href="https://mbs.microsoft.com/customersource/"&gt;CustomerSource&lt;/a&gt;)&lt;br&gt;
- forum topic: &lt;a href="http://www.microsoft.com/communities/newsgroups/list/en-us/default.aspx?dg=microsoft.public.axapta.programming"&gt;microsoft.public.axapta.programming&lt;/a&gt; - &lt;a href="http://www.microsoft.com/communities/newsgroups/list/en-us/default.aspx?dg=microsoft.public.axapta.programming&amp;amp;mid=1344f4d0-a6c0-49e4-b692-cb1c0227a4a5"&gt;Currupt records in UtilIdElement and UtilElements&lt;/a&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;&lt;span style="color:#990000;"&gt;Warning:&lt;/span&gt;&lt;/strong&gt; Serious problems might occur if you modify the &lt;strong&gt;UtilIdElements&lt;/strong&gt; table using this or another method. Modify system tables at your own risk.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;The code:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Job1(Args _args) 
{ 
    UtilIdElements utilElement; 
    ; 

    &lt;span class="kwrd"&gt;ttsbegin;&lt;/span&gt; 

    &lt;span class="kwrd"&gt;select&lt;/span&gt; utilElement 
        &lt;span class="kwrd"&gt;where&lt;/span&gt; utilElement.name == &lt;span class="str"&gt;'myElementName'&lt;/span&gt;
        &amp;amp;&amp;amp; utilElement.utilLevel == utilEntryLevel::cus &lt;span class="rem"&gt;// any layer &lt;/span&gt;
        &amp;amp;&amp;amp; utilElement.recordType == utilElementType::Table; &lt;span class="rem"&gt;// object type &lt;/span&gt;

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (utilelement) 
    { 
        utilElement.delete(); 

        &lt;span class="kwrd"&gt;ttscommit;&lt;/span&gt; 
        info(&lt;span class="str"&gt;'Record should be deleted now.'&lt;/span&gt;); 
    } 
    &lt;span class="kwrd"&gt;else&lt;/span&gt; 
    { 
        &lt;span class="kwrd"&gt;ttsAbort;&lt;/span&gt; 
        info(&lt;span class="str"&gt;'Could not delete record, or it was not found.'&lt;/span&gt;); 
    } 
}
&lt;/pre&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6955268887409974396?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6955268887409974396/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6955268887409974396' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6955268887409974396'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6955268887409974396'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2009/06/how-to-delete-aot-nodes-by-code.html' title='How to delete AOT nodes by code (UtilIdElements solution)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4624957238115621769</id><published>2009-06-27T10:20:00.000-07:00</published><updated>2009-07-13T17:52:43.512-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>AOS crashed due corrupted node in the AOT</title><content type='html'>&lt;strong&gt;&lt;span style="color:#990000;"&gt;Warning:&lt;/span&gt;&lt;/strong&gt; this post is only informative, do not try to replicate the problem described here in a production environment. !!!!&lt;br&gt;&lt;br&gt;

&lt;strong&gt;The problem:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

The problem occurred when we created a &lt;em&gt;'View'&lt;/em&gt; with one &lt;em&gt;circular reference&lt;/em&gt;. After that, every time we tried to click over &lt;em&gt;"Data Dictionary\Tables"&lt;/em&gt; or &lt;em&gt;"Data Dictionary\Views"&lt;/em&gt;, the AOS &lt;strong&gt;crashes&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;How to reproduce the problem:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;&lt;span style="color:#990000;"&gt;Warning:&lt;/span&gt;&lt;/strong&gt; this post is only informative, do not try to replicate the problem described here in a production environment. !!!!&lt;br&gt;&lt;br&gt;

0. Make a backup.  Also, make a copy of the AxCus.AOD file.&lt;br&gt;
1. Create a simple view (ex. View1).&lt;br&gt;
2. Add a new DataSource manually. Then, open DataSource's properties dialog and specify in the &lt;em&gt;table&lt;/em&gt; field the name of the view you have created (ex. View1).&lt;br&gt;
3. &lt;span style="color:#990000;"&gt;&lt;strong&gt;STOP&lt;/strong&gt; at this point if you dont want to crash the AOS !!!.&lt;/span&gt;&lt;br&gt;
4. Expand the DataSource node. Drag the field &lt;em&gt;CreatedBy&lt;/em&gt; to the view's fields. It will create the &lt;em&gt;CreatedBy1&lt;/em&gt; field.&lt;br&gt;
5. Save it if you are sure you want to continue. After this action, your AOS will crash. (&lt;strong&gt;oops&lt;/strong&gt; !)&lt;br&gt;&lt;br&gt;

You can try to recover the error by deleting the corrupted node &lt;em&gt;(ex. View1 or CreatedBy1 field)&lt;/em&gt; using this method: &lt;a href="http://olondono.blogspot.com/2007/12/how-to-delete-aot-objects-axaxapta.html"&gt;How to delete AOT objects (AX/Axapta)&lt;/a&gt; or this other: &lt;a href="http://olondono.blogspot.com/2009/06/how-to-delete-aot-nodes-by-code.html"&gt;How to delete AOT nodes by code (UtilIdElements solution)&lt;/a&gt;.  None of them will work!!!.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;The solution:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

After several tries, the only solution was open the &lt;em&gt;AxCus.AOD&lt;/em&gt; file in a binary editor (Visual Studio is enough) and perform the next steps.&lt;br&gt;&lt;br&gt;

&lt;span style="color:#990000;"&gt;&lt;strong&gt;Warning:&lt;/strong&gt;&lt;/span&gt; Serious problems might occur if you modify the AxCus.AOD file using this or another method.  Modify system files at your own risk.&lt;br&gt;&lt;br&gt;

0. Make a backup.  Also, make a copy of the AxCus.AOD file.&lt;br&gt;
1. Stop the AOS and open the &lt;em&gt;AxCus.AOD&lt;/em&gt; in a binary editor.&lt;br&gt;
2. Locate the &lt;em&gt;"CreatedBy1"&lt;/em&gt; field data (or your corrupted node's name).  Normally, it should be near to the end of the file.  &lt;em&gt;(Look at pictures for details).&lt;/em&gt;&lt;br&gt; 
3. Change the reference data. It is above the field's name.  Put the value &lt;strong&gt;FF FF&lt;/strong&gt; (&lt;em&gt;65,535&lt;/em&gt;) in the parent and field ids.&lt;br&gt;
4. Save the file.&lt;br&gt;
5. Delete the index file &lt;strong&gt;axapd.aoi&lt;/strong&gt;.&lt;br&gt;
6. Start the AOS again.&lt;br&gt;
7. Delete the corrupted view.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;&lt;em&gt;Image with the corrupted node:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;a href="http://4.bp.blogspot.com/_klu-RAVtjKg/SkZs4bZOtbI/AAAAAAAAAGI/9PZP2oI5xL4/s1600-h/Crashed.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 262px;" src="http://4.bp.blogspot.com/_klu-RAVtjKg/SkZs4bZOtbI/AAAAAAAAAGI/9PZP2oI5xL4/s320/Crashed.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5352084923858466226" /&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;&lt;em&gt;Image with the fixed node:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;a href="http://2.bp.blogspot.com/_klu-RAVtjKg/SkZtF5iKTaI/AAAAAAAAAGQ/7eIOFBlsxCw/s1600-h/Fixed.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 263px;" src="http://2.bp.blogspot.com/_klu-RAVtjKg/SkZtF5iKTaI/AAAAAAAAAGQ/7eIOFBlsxCw/s320/Fixed.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5352085155287289250" /&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;

It is probable the corrupted node stays alive in the AOT, so you can try the following code to remove it:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Job1(Args _args) 
{ 
    UtilIdElements utilElement; 
    ; 

    ttsbegin; 

    select utilElement 
        &lt;span class="kwrd"&gt;where&lt;/span&gt; utilElement.id == 65535; &lt;span class="rem"&gt;// Invalid ID we have writed in the AxCus.AOD file &lt;/span&gt;

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (utilelement) 
    { 
        utilElement.delete(); 

        ttscommit; 
        info(&lt;span class="str"&gt;'Record should be deleted now.'&lt;/span&gt;); 
    } 
    &lt;span class="kwrd"&gt;else&lt;/span&gt; 
    { 
        ttsAbort; 
        info(&lt;span class="str"&gt;'Could not delete record, or it was not found.'&lt;/span&gt;); 
    } 
}
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4624957238115621769?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4624957238115621769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4624957238115621769' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4624957238115621769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4624957238115621769'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2009/06/aos-crashed-due-corrupted-node-in-aot.html' title='AOS crashed due corrupted node in the AOT'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_klu-RAVtjKg/SkZs4bZOtbI/AAAAAAAAAGI/9PZP2oI5xL4/s72-c/Crashed.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2635780973090310638</id><published>2009-03-17T08:27:00.000-07:00</published><updated>2009-03-17T08:33:58.570-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='Source Code'/><title type='text'>Posting a ledger journal</title><content type='html'>Here is the adapted example for posting a ledger journal line.  Simply replace values between &lt;strong&gt;#s&lt;/strong&gt; &lt;em&gt;(#value#)&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ExampleLedgerJournal(Args _args)
{
    LedgerJournalTable      ledgerJournalTable;
    LedgerJournalTrans      ledgerJournalTrans;
    LedgerJournalCheckPost  ledgerJournalCheckPost;
    NumberSeq               numberSeq;
    ;

    &lt;span class="kwrd"&gt;ttsbegin&lt;/span&gt;;

    &lt;span class="rem"&gt;// Journal name&lt;/span&gt;
    ledgerJournalTable.JournalName = &lt;span class="str"&gt;"#JOURNALNAME#"&lt;/span&gt;; &lt;span class="rem"&gt;// ex. Daily, daytrans, etc.&lt;/span&gt;
    ledgerJournalTable.initFromLedgerJournalName();
    ledgerJournalTable.Name = &lt;span class="str"&gt;"#DESCRIPTION#"&lt;/span&gt;;  &lt;span class="rem"&gt;// description for this journal&lt;/span&gt;
    ledgerJournalTable.insert();

    &lt;span class="rem"&gt;// Voucher&lt;/span&gt;
    numberSeq = NumberSeq::newGetVoucherFromCode(LedgerJournalName::find(ledgerJournalTable.JournalName).VoucherSeries);
    ledgerJournalTrans.Voucher = numberSeq.voucher();

    &lt;span class="rem"&gt;// Lines&lt;/span&gt;
    ledgerJournalTrans.JournalNum = ledgerJournalTable.JournalNum;
    ledgerJournalTrans.CurrencyCode = CompanyInfo::standardCurrency();
    ledgerJournalTrans.ExchRate = Currency::exchRate(ledgerJournalTrans.CurrencyCode);
    ledgerJournalTrans.AccountNum = &lt;span class="str"&gt;"#ACCOUNT#"&lt;/span&gt;;
    ledgerJournalTrans.AccountType = LedgerJournalACType::Ledger;
    ledgerJournalTrans.AmountCurDebit = &lt;span class="str"&gt;#VALUE#&lt;/span&gt;;
    ledgerJournalTrans.TransDate = systemDateGet(); &lt;span class="rem"&gt;//Avoid the Today function&lt;/span&gt;
    ledgerJournalTrans.OffsetAccount = &lt;span class="str"&gt;"#OFFSET ACCOUNT#"&lt;/span&gt;;
    ledgerJournalTrans.Txt = &lt;span class="str"&gt;"#TXT#"&lt;/span&gt;;
    ledgerJournalTrans.insert();

    &lt;span class="rem"&gt;//Posting the Journal&lt;/span&gt;
    ledgerJournalCheckPost = LedgerJournalCheckPost::newLedgerJournalTable(ledgerJournalTable, NoYes::Yes);
    ledgerJournalCheckPost.run();
    
    &lt;span class="kwrd"&gt;ttscommit&lt;/span&gt;;
}
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Note:&lt;/strong&gt; you can expand to include more than one line.  Enjoy!&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2635780973090310638?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2635780973090310638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2635780973090310638' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2635780973090310638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2635780973090310638'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2009/03/posting-ledger-journal.html' title='Posting a ledger journal'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2293975659477287437</id><published>2009-02-06T08:18:00.000-08:00</published><updated>2009-02-06T19:06:11.311-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Delivering large strings through WCF</title><content type='html'>If you have trouble sending large strings through WCF (more than 8192 bytes), it is probable you need to configure the parameter &lt;em&gt;ReaderQuotas.MaxStringContentLength&lt;/em&gt; (default value is 8192).  This parameter should be configured in both sides (client and server) as needed.&lt;br&gt;&lt;br&gt;

Set this by code:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
NetTcpBinding tcp = &lt;span class="kwrd"&gt;new&lt;/span&gt; NetTcpBinding();
tcp.ReaderQuotas.MaxStringContentLength = 65535;
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

or modifying the config file:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
...
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;binding&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="myTcpBinding"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;readerQuotas&lt;/span&gt; &lt;span class="attr"&gt;maxStringContentLength&lt;/span&gt;&lt;span class="kwrd"&gt;="65535"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    ...
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;binding&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
...&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2293975659477287437?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2293975659477287437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2293975659477287437' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2293975659477287437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2293975659477287437'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2009/02/delivering-large-strings-through-wcf.html' title='Delivering large strings through WCF'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8012923962842168537</id><published>2009-01-14T16:38:00.001-08:00</published><updated>2009-01-14T17:26:56.412-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>MG Instant Messaging for AX (Freeware)</title><content type='html'>Based in &lt;strong&gt;MeetGate&lt;/strong&gt;, I've developed this simple messaging system for use in DAX.  This is not a fully Instant Messaging system yet, but provides a simple and efficient chat for improve co-workers communication, and the best part, is freeware.&lt;br&gt;&lt;br&gt;

The server includes only a small subset of &lt;strong&gt;MeetGate's features&lt;/strong&gt; and was developed using .NET Framework 3.5 (WCF).  I hope someday I could improve it with others important services like the &lt;strong&gt;"File Publication"&lt;/strong&gt; for automatic distribution of files using the &lt;em&gt;Presence Indicator&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

You can use it for free under terms of &lt;a href="http://www.opensource.org/licenses/ms-pl.html"&gt;The Microsoft Public License (Ms-PL)&lt;/a&gt;.&lt;br&gt;&lt;br&gt;

&lt;a href="http://4.bp.blogspot.com/_klu-RAVtjKg/SW6HnViyxOI/AAAAAAAAADQ/coloEhUYuXw/s1600-h/MGChat.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 232px;" src="http://4.bp.blogspot.com/_klu-RAVtjKg/SW6HnViyxOI/AAAAAAAAADQ/coloEhUYuXw/s320/MGChat.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5291315722074637538" /&gt;&lt;/a&gt;

&lt;strong&gt;Installation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

Copy the server's files anywhere and install the windows service by running the command line: &lt;em&gt;MGServerSvc /install&lt;/em&gt;.  For uninstall it, simply run in the command line: &lt;em&gt;MGServerSvc /uninstall&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

The server's address can be configured by creating or editing the &lt;em&gt;MGServerSvc.exe.config&lt;/em&gt; file as:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;appSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;="BaseAddress"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="net.tcp://localhost:8000/MGServerService"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;appSettings&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

You need to copy the following files to the DAX client's directory, usually located in &lt;strong&gt;C:\Program Files\Microsoft Dynamics AX\40\Client\Bin&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;

MGControlAX.dll&lt;br&gt;
MGLibrary.dll&lt;br&gt;
MGClientLibrary.dll&lt;br&gt;&lt;br&gt;

For the Dynamics AX client, you need to install the ActiveX &lt;em&gt;MGControlAX.dll&lt;/em&gt;.  Dynamics AX cannot process events from managed components so the only way to notify events in DAX is by building an ActiveX control.  In my case, I developed the &lt;em&gt;MGControlAX.dll&lt;/em&gt; and before use it, you must register it as:&lt;br&gt;&lt;br&gt;

&lt;strong&gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\RegAsm MGControlAX.dll /tlb /codebase&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

NOTE: Remember the parameters: &lt;em&gt;/tlb /codebase&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

After that, you can import the .XPO project and edit the &lt;em&gt;login&lt;/em&gt; method in the form &lt;em&gt;MGToolbar&lt;/em&gt;.  This form runs as a DAX toolbar so you can always access its buttons: &lt;em&gt;login/logout&lt;/em&gt;, &lt;em&gt;contacts&lt;/em&gt; and &lt;em&gt;close&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; Login()
{
    UserId      currentUserId = curuserid();
    UserInfo    userInfo;
    ;

    select firstonly userInfo
        &lt;span class="kwrd"&gt;where&lt;/span&gt; userInfo.id == currentUserId;

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (userInfo.name != &lt;span class="str"&gt;""&lt;/span&gt;)
        MGControlX.UserName(userInfo.name);
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        MGControlX.UserName(userInfo.Id);

    MGControlX.Domain(userInfo.networkDomain);

    MGControlX.BaseAddress(&lt;span class="str"&gt;"net.tcp://localhost:8000/MGServerService/MGServerService"&lt;/span&gt;);

    MGControlX.Login();
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

If you press the button contacts and it will show you the list of available contacts &lt;strong&gt;(This version is NOT users limited)&lt;/strong&gt;.  If you make double click over an online contact you can start chatting with him.  All changes in any contact's status is notified (Online/Offline) and you can see the icon as green or red respectively.&lt;br&gt;&lt;br&gt;

Files for download:&lt;br&gt;&lt;br&gt;

&lt;a href="http://cid-226d38f3ed72231f.skydrive.live.com/self.aspx/.Public/MGServer.zip"&gt;Server's files&lt;/a&gt;&lt;br&gt;
&lt;a href="http://cid-226d38f3ed72231f.skydrive.live.com/self.aspx/.Public/PrivateProject%7C_MG.xpo"&gt;The XPO file&lt;/a&gt;&lt;br&gt;
&lt;a href="http://cid-226d38f3ed72231f.skydrive.live.com/self.aspx/.Public/MGClient.zip"&gt;Client's files&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8012923962842168537?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8012923962842168537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8012923962842168537' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8012923962842168537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8012923962842168537'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2009/01/mg-instant-messaging-for-ax-freeware.html' title='MG Instant Messaging for AX (Freeware)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_klu-RAVtjKg/SW6HnViyxOI/AAAAAAAAADQ/coloEhUYuXw/s72-c/MGChat.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2759791502946756746</id><published>2008-12-29T21:48:00.000-08:00</published><updated>2008-12-31T17:51:57.702-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Source Code'/><title type='text'>WCF interface for Dynamics AX</title><content type='html'>In DAX you must implement a lot of interfaces, some of them using ADO, AIF, WS, MSMQ, etc.  I have developed my own interface using WCF (.NET Framework 3.5).&lt;br&gt;&lt;br&gt;

In this interface, I built two applications: the server that interacts with DAX by using the &lt;strong&gt;Business Connector&lt;/strong&gt; and the client that is a standalone application that doesn't need ADSI and can run outside of the organization, for example, to send or receive data from partners automatically.&lt;br&gt;&lt;br&gt;

&lt;a href="http://2.bp.blogspot.com/_klu-RAVtjKg/SVm5Ulws1BI/AAAAAAAAACo/lOxtHXqDucQ/s1600-h/AXInterface.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 116px;" src="http://2.bp.blogspot.com/_klu-RAVtjKg/SVm5Ulws1BI/AAAAAAAAACo/lOxtHXqDucQ/s320/AXInterface.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5285459401080886290" /&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;

The example bellow includes the source code for Visual Studio 2008 and the DAX project (.xpo).  In this project, I transport data from a local database (MyTable) to an owner table in DAX: WCFMyTable.  Also, I can detect changes from any DAX table and send data to the client. &lt;em&gt;For example: when any customer is added, I can replicate this data to legacy systems.&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;a href="http://1.bp.blogspot.com/_klu-RAVtjKg/SVm77P_lyLI/AAAAAAAAACw/DGG0aaXvXh8/s1600-h/AXInterfaceXPO.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 250px; height: 254px;" src="http://1.bp.blogspot.com/_klu-RAVtjKg/SVm77P_lyLI/AAAAAAAAACw/DGG0aaXvXh8/s320/AXInterfaceXPO.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5285462264275912882" /&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;

The DAX project includes the following elements:&lt;br&gt;&lt;br&gt;

&lt;strong&gt;WCFMyTable:&lt;/strong&gt; this is a sample table for receive data from the client side.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;WCFConnTest:&lt;/strong&gt; this class is used to test the connection with DAX.  The method &lt;em&gt;getCustomer&lt;/em&gt; can be used for retrieve the first customer in the table &lt;em&gt;CustTable&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;WCFTask:&lt;/strong&gt; is a class that encapsulates the access to any table we want to send to the client.&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;em&gt;getRecord&lt;/em&gt; - returns a &lt;em&gt;common&lt;/em&gt; record.&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;em&gt;getRecordAxXml&lt;/em&gt; - returns the xml representation for the record this task is belong to.&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;em&gt;MarkAsOK&lt;/em&gt; - update the task with a successful result when the client has processed it.&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;em&gt;MarkAsFAILED&lt;/em&gt; - update the task as "failed" when the client has processed it and an error was raised.  Tasks with errors are not removed from the table for debugging purposes.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;WCFSender:&lt;/strong&gt;  this is the class that can be used for create a task for deliver to the client.  You must override the &lt;em&gt;update&lt;/em&gt;, &lt;em&gt;insert&lt;/em&gt; and &lt;em&gt;delete&lt;/em&gt; methods in the table you want to send.  Here are the &lt;em&gt;insert&lt;/em&gt; and &lt;em&gt;update&lt;/em&gt; methods from the &lt;strong&gt;Dimensions&lt;/strong&gt; table:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; insert()
{
    super();

    &lt;span class="rem"&gt;// Send this task&lt;/span&gt;
    WCFSender::SendThisRecord(&lt;span class="kwrd"&gt;this&lt;/span&gt;);
    &lt;span class="rem"&gt;// End&lt;/span&gt;
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; update()
{
    DimensionSetCombination dimensionSetCombination;
    ;

    ttsbegin;

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.Closed != &lt;span class="kwrd"&gt;this&lt;/span&gt;.orig().Closed)
    {
        update_recordset dimensionSetCombination
            setting active = !&lt;span class="kwrd"&gt;this&lt;/span&gt;.Closed
            &lt;span class="kwrd"&gt;where&lt;/span&gt; dimensionSetCombination.Dimension[Dimensions::code2ArrayIdx(&lt;span class="kwrd"&gt;this&lt;/span&gt;.DimensionCode)] == &lt;span class="kwrd"&gt;this&lt;/span&gt;.Num;
    }

    super();

    ttscommit;

    &lt;span class="rem"&gt;// Send this task&lt;/span&gt;
    WCFSender::SendThisRecord(&lt;span class="kwrd"&gt;this&lt;/span&gt;);
    &lt;span class="rem"&gt;// End&lt;/span&gt;
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;WCFTasks:&lt;/strong&gt; this table store all tasks pending for deliver to the client.  The table only store the reference to the record by &lt;em&gt;tableId&lt;/em&gt; and &lt;em&gt;recId&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;WCFInterface:&lt;/strong&gt; this is the main class that is used for read tasks from server (method &lt;em&gt;getNextTask&lt;/em&gt;) and send data to server (method &lt;em&gt;ProcessTask&lt;/em&gt;).&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;em&gt;getNextTask&lt;/em&gt;:  with this method we can get the next task for processing in the client side and at the same time, we can update the previous one.  By using the &lt;em&gt;Company&lt;/em&gt; and &lt;em&gt;previousCompany&lt;/em&gt; parameters, we can read tasks from several companies.&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;em&gt;ProcessTask&lt;/em&gt;:  this is the method called when we want to send data back to DAX.  We can also send multi-company data by specifying the &lt;em&gt;Company&lt;/em&gt; parameter.&lt;br&gt;&lt;br&gt;

Here are the files for download:&lt;br&gt;&lt;br&gt;

&lt;a href="http://cid-226d38f3ed72231f.skydrive.live.com/self.aspx/.Public/AXInterface.zip"&gt;Visual Studio 2008 project (AXInterface.zip)&lt;/a&gt;&lt;br&gt;
&lt;a href="http://cid-226d38f3ed72231f.skydrive.live.com/self.aspx/.Public/PrivateProject%7C_WCFInterface.xpo"&gt;The DAX project: WCFInterface.xpo&lt;/a&gt;&lt;br&gt;
&lt;a href="http://cid-226d38f3ed72231f.skydrive.live.com/self.aspx/.Public/MyTable.sql"&gt;MyTable.sql definition&lt;/a&gt;&lt;br&gt;&lt;br&gt;

License: &lt;a href="http://www.opensource.org/licenses/ms-pl.html"&gt;The Microsoft Public License (Ms-PL)&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2759791502946756746?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2759791502946756746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2759791502946756746' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2759791502946756746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2759791502946756746'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/12/wcf-interface-for-dynamics-ax.html' title='WCF interface for Dynamics AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_klu-RAVtjKg/SVm5Ulws1BI/AAAAAAAAACo/lOxtHXqDucQ/s72-c/AXInterface.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-918461121673103814</id><published>2008-12-28T20:24:00.000-08:00</published><updated>2008-12-28T20:39:16.528-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Truncated real fields (ex. LineNum) when table is exported as XML</title><content type='html'>When you are using the method &lt;strong&gt;xml()&lt;/strong&gt; for exporting records from any table in DAX you could get inconsistency data for real fields.&lt;br&gt;&lt;br&gt;

The problem is located inside the method &lt;strong&gt;Global::xmlstring&lt;/strong&gt;.  In this method, the real type is exported only with 2 decimals.  You must override this method in the appropiated layer to export &lt;em&gt;reals&lt;/em&gt; with 8, 10, 12 or more number of decimals.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Returns a XML string describing the given value of the given type.&lt;/span&gt;
&lt;span class="kwrd"&gt;static&lt;/span&gt; str xmlString(anytype &lt;span class="kwrd"&gt;value&lt;/span&gt;, Types theType, &lt;span class="kwrd"&gt;int&lt;/span&gt; indent=0)
{
    str r;
    Object o;
    Common record;

    ...

    r = strrep(&lt;span class="str"&gt;' '&lt;/span&gt;, indent);

    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (theType)
    {

    ...
    
    &lt;span class="rem"&gt;// Modified: original allows only 2 decimals,&lt;/span&gt;
    &lt;span class="rem"&gt;// now, we allow 12&lt;/span&gt;
    &lt;span class="kwrd"&gt;case&lt;/span&gt; Types::Real:       r += num2str(&lt;span class="kwrd"&gt;value&lt;/span&gt;,
                                        &lt;span class="rem"&gt;/* min chars */&lt;/span&gt; 1,
                                        &lt;span class="rem"&gt;/* decimals */&lt;/span&gt;  12,  &lt;span class="rem"&gt;// Original = 2&lt;/span&gt;
                                        &lt;span class="rem"&gt;/* decimals = point */&lt;/span&gt; 1,
                                        &lt;span class="rem"&gt;/* no thousand sep */&lt;/span&gt; 0); &lt;span class="kwrd"&gt;break&lt;/span&gt;;

    ...

    }
    &lt;span class="kwrd"&gt;return&lt;/span&gt; r;
}&lt;/pre&gt;
&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-918461121673103814?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/918461121673103814/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=918461121673103814' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/918461121673103814'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/918461121673103814'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/12/truncated-real-fields-ex-linenum-when.html' title='Truncated real fields (ex. LineNum) when table is exported as XML'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5956958607623952611</id><published>2008-12-13T14:41:00.000-08:00</published><updated>2008-12-13T16:14:37.825-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Source Code'/><title type='text'>Some features in .NET Framework 3.0</title><content type='html'>&lt;strong&gt;Implicitly typed variables and arrays&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

Implicit variables are useful for improve writing and reading code (not in all cases) and they are key for LINQ query expressions:&lt;br&gt;&lt;br&gt;

Before:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; dict = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();
&lt;span class="kwrd"&gt;int&lt;/span&gt;[] Numbers = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;[] { 1, 2, 3, 4, 5 };
&lt;span class="kwrd"&gt;string&lt;/span&gt;[] s = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] { &lt;span class="str"&gt;"a"&lt;/span&gt;, &lt;span class="str"&gt;"b"&lt;/span&gt;, &lt;span class="str"&gt;"c"&lt;/span&gt;, &lt;span class="str"&gt;"d"&lt;/span&gt; };
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

Now:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
var dict = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();
var Numbers = &lt;span class="kwrd"&gt;new&lt;/span&gt;[] { 1, 2, 3, 4, 5 };
var s = &lt;span class="kwrd"&gt;new&lt;/span&gt;[] { &lt;span class="str"&gt;"a"&lt;/span&gt;, &lt;span class="str"&gt;"b"&lt;/span&gt;, &lt;span class="str"&gt;"c"&lt;/span&gt;, &lt;span class="str"&gt;"d"&lt;/span&gt; };
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Extensions Methods&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

That's an amazing feature for extend interfaces and classes that we don't have the source code or we don't want to modify directly.&lt;br&gt;&lt;br&gt;

&lt;em&gt;Example:&lt;/em&gt; Suppose you have an interface that has two properties: &lt;em&gt;Name&lt;/em&gt; and &lt;em&gt;Age&lt;/em&gt;.  Also, it has a method that display its data as &lt;em&gt;'Name=NameValue Age=AgeValue'&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; ITestClass
{
    &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }
    &lt;span class="kwrd"&gt;int&lt;/span&gt; Age { get; set; }

    &lt;span class="kwrd"&gt;void&lt;/span&gt; Show();
}
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

But, we need to show this data in a different way in several parts of our code, for example: &lt;em&gt;'NameValue (AgeValue)'&lt;/em&gt;.  By extending this interface we can simply invoke the method as &lt;em&gt;'tc.ShowCustom();'&lt;/em&gt; like if &lt;em&gt;ShowCustom &lt;/em&gt;is part of this interface:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TestClassExtension
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ShowCustom(&lt;span class="kwrd"&gt;this&lt;/span&gt; ITestClass tc)
    {
        MessageBox.Show(tc.Name + &lt;span class="str"&gt;" ("&lt;/span&gt; + tc.Age.ToString() + &lt;span class="str"&gt;")"&lt;/span&gt;);
    }
}

...

ITestClass tc = GetTestClassInteface();
tc.Name = &lt;span class="str"&gt;"Oscar"&lt;/span&gt;;
tc.Age = 36;

tc.Show();
tc.ShowCustom(); &lt;span class="rem"&gt;// Now it appears like if this method is part of ITestClass (!!! amazing !!!)&lt;/span&gt;

&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; You can extend standard and base classes/interfaces like String, IEnumerator, etc.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Lambda Expressions&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

They are key for LINQ expressions and for reduce the use of delegates, here a little example:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
var list = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();

list.Add(&lt;span class="str"&gt;"one"&lt;/span&gt;);
list.Add(&lt;span class="str"&gt;"two"&lt;/span&gt;);
list.Add(&lt;span class="str"&gt;"three"&lt;/span&gt;);

&lt;span class="kwrd"&gt;bool&lt;/span&gt; bExist = list.Exists(&lt;span class="kwrd"&gt;delegate&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt; s) { &lt;span class="kwrd"&gt;return&lt;/span&gt; s == &lt;span class="str"&gt;"two"&lt;/span&gt;; });
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

And using &lt;em&gt;Lambda Expressions&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;bool&lt;/span&gt; bExist = list.Exists(s =&amp;gt; s == &lt;span class="str"&gt;"two"&lt;/span&gt;);
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Anonymous types&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

Allows the on-the-fly creation of structures:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
var person = &lt;span class="kwrd"&gt;new&lt;/span&gt; { Name = &lt;span class="str"&gt;"Oscar"&lt;/span&gt;, Age = 36 };

MessageBox.Show(person.Name + &lt;span class="str"&gt;"("&lt;/span&gt; + person.Age + &lt;span class="str"&gt;")"&lt;/span&gt;);
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Object/Collection Initializers&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

We can now initialize any property when we are creating some instance for objects or collections:&lt;br&gt;&lt;br&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
Timer t = &lt;span class="kwrd"&gt;new&lt;/span&gt; Timer() { Interval = 30000, Enabled = &lt;span class="kwrd"&gt;true&lt;/span&gt; };

var list = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; { &lt;span class="str"&gt;"one"&lt;/span&gt;, &lt;span class="str"&gt;"two"&lt;/span&gt;, &lt;span class="str"&gt;"three"&lt;/span&gt; };
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

References:&lt;br&gt;&lt;br&gt;

&lt;a href="http://www.programmersheaven.com/2/CSharp3-1"&gt;C# 3.0 Tutorial&lt;/a&gt; By Jonathan Worthington&lt;br&gt;&lt;br&gt;
&lt;a href="http://msdn.microsoft.com/en-us/library/ms364047(VS.80).aspx"&gt;C# Version 3.0 Specification&lt;/a&gt;  MSDN&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5956958607623952611?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5956958607623952611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5956958607623952611' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5956958607623952611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5956958607623952611'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/12/some-features-in-net-framework-30.html' title='Some features in .NET Framework 3.0'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8198804252295284163</id><published>2008-11-14T20:32:00.000-08:00</published><updated>2008-11-14T20:41:35.081-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Error: "The element &lt;WFCompilationResourcesWithNoCulture&gt; beneath element &lt;ItemGroup&gt; is unrecognized..."</title><content type='html'>When you try to compile a workflow project (WWF) you got an error like this one: &lt;em&gt;Error 1 The element &amp;lt;WFCompilationResourcesWithNoCulture&amp;gt; beneath element &amp;lt;ItemGroup&amp;gt; is unrecognized.&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

Open the project's file (.csproj) using the &lt;em&gt;Notepad&lt;/em&gt; and change the framework version from 3.5 to 3.0, it must look as shown below:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
  &amp;lt;Import Project="$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.0\Workflow.Targets" /&amp;gt;
&lt;/pre&gt;
&lt;br&gt;
&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8198804252295284163?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8198804252295284163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8198804252295284163' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8198804252295284163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8198804252295284163'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/11/error-element-beneath-element-is.html' title='Error: &quot;The element &amp;lt;WFCompilationResourcesWithNoCulture&amp;gt; beneath element &amp;lt;ItemGroup&amp;gt; is unrecognized...&quot;'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-527875060993257417</id><published>2008-10-24T18:53:00.000-07:00</published><updated>2008-10-24T19:37:10.658-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Drawing objects in .NET (C#)</title><content type='html'>Here is a little example of using some available objects for drawing in .NET (&lt;em&gt;namespace &lt;strong&gt;System.Drawing&lt;/strong&gt;&lt;/em&gt;):&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Form1_Paint(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, PaintEventArgs e)
{
    &lt;span class="rem"&gt;// Create a graphics object from the form&lt;/span&gt;
    Graphics g = &lt;span class="kwrd"&gt;this&lt;/span&gt;.CreateGraphics();
    
    &lt;span class="rem"&gt;// Create a pen object&lt;/span&gt;
    Pen p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Pen(Color.Red, 7);
    
    &lt;span class="rem"&gt;// Draw one horizontal line line&lt;/span&gt;
    g.DrawLine(p, &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(10, 10), &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(100, 10));

    &lt;span class="rem"&gt;// Drawing an image&lt;/span&gt;
    Image img = Image.FromFile(&lt;span class="str"&gt;"C:\\MyPicture.jpg"&lt;/span&gt;);
    g.DrawImage(img, 120, 20, img.Width, img.Height); 

    &lt;span class="rem"&gt;// Array of points for some polygon&lt;/span&gt;
    Point[] points = &lt;span class="kwrd"&gt;new&lt;/span&gt; Point[]
    {
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(20, 20),
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(20, 100),
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(50, 65),
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(100, 100),
        &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(85, 40)
    };

    Brush bs = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidBrush(Color.Aquamarine);

    &lt;span class="rem"&gt;// Fill a shape&lt;/span&gt;
    g.FillPolygon(bs, points);

    &lt;span class="rem"&gt;// Draw a shape defined by the array of points&lt;/span&gt;
    g.DrawPolygon(&lt;span class="kwrd"&gt;new&lt;/span&gt; Pen(Color.Black, 2), points);

    &lt;span class="rem"&gt;// Draw a text&lt;/span&gt;
    Font f = &lt;span class="kwrd"&gt;new&lt;/span&gt; Font(&lt;span class="str"&gt;"Arial"&lt;/span&gt;, 40, FontStyle.Bold);
    g.DrawString(&lt;span class="str"&gt;"Hello, World!"&lt;/span&gt;, f, Brushes.Blue, 10, 200);

    &lt;span class="rem"&gt;// Draw a icon&lt;/span&gt;
    g.DrawIcon(SystemIcons.Question, 260, 40);
    g.DrawIcon(SystemIcons.Shield, 260, 80);
}
&lt;/pre&gt;&lt;br&gt;

Another way for drawing a picture is using the Bitmap object that provides methods for save it:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Form1_Paint(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, PaintEventArgs e)
{
    &lt;span class="rem"&gt;// Create a graphics object from the form&lt;/span&gt;
    Graphics g = &lt;span class="kwrd"&gt;this&lt;/span&gt;.CreateGraphics();

    &lt;span class="rem"&gt;// Read and draw the bitmap&lt;/span&gt;
    Bitmap bmp = &lt;span class="kwrd"&gt;new&lt;/span&gt; Bitmap(&lt;span class="str"&gt;"C:\\MyPicture.jpg"&lt;/span&gt;);

    g.DrawImage(bmp, 10, 10, bmp.Width, bmp.Height);
}
&lt;/pre&gt;&lt;br&gt;

Saving a modified bitmap:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button3_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span class="rem"&gt;// Read the bitmap&lt;/span&gt;
    Bitmap bmp = &lt;span class="kwrd"&gt;new&lt;/span&gt; Bitmap(&lt;span class="str"&gt;"C:\\MyPicture.jpg"&lt;/span&gt;);

    &lt;span class="rem"&gt;// Create a graphics from this bitmap&lt;/span&gt;
    Graphics g = Graphics.FromImage(bmp);

    &lt;span class="rem"&gt;// Draw a watermark&lt;/span&gt;
    Font f = &lt;span class="kwrd"&gt;new&lt;/span&gt; Font(&lt;span class="str"&gt;"Arial"&lt;/span&gt;, 2, FontStyle.Bold);
    g.DrawString(&lt;span class="str"&gt;"That's me"&lt;/span&gt;, f, Brushes.White, 10, 10);

    &lt;span class="rem"&gt;// Finally, save the bitmap in any available format from ImageFormat&lt;/span&gt;
    bmp.Save(&lt;span class="str"&gt;"c:\\MyPicture2.jpg"&lt;/span&gt;, ImageFormat.Jpeg);
}
&lt;/pre&gt;&lt;br&gt;

Or you can create a new bitmap for drawing inside it:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button3_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span class="rem"&gt;// Create a new bitmap of 100x140 pixels&lt;/span&gt;
    Bitmap bmp = &lt;span class="kwrd"&gt;new&lt;/span&gt; Bitmap(100, 140);

    &lt;span class="rem"&gt;// Create a graphics from this bitmap&lt;/span&gt;
    Graphics g = Graphics.FromImage(bmp);
    
    &lt;span class="rem"&gt;// Fill its background with white color&lt;/span&gt;
    g.FillRectangle(&lt;span class="kwrd"&gt;new&lt;/span&gt; SolidBrush(Color.White), 0, 0, bmp.Width, bmp.Height);
    
    &lt;span class="rem"&gt;// Draw some objects&lt;/span&gt;
    Pen p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Pen(Color.Blue, 8);
    g.DrawLine(p, 10, 10, 10, 80);
    g.DrawIcon(SystemIcons.Shield, 40, 40);
    
    &lt;span class="rem"&gt;// Save the bitmap&lt;/span&gt;
    bmp.Save(&lt;span class="str"&gt;"c:\\MyPicture3.jpg"&lt;/span&gt;, System.Drawing.Imaging.ImageFormat.Jpeg);
}
&lt;/pre&gt;&lt;br&gt;

Anyway, there are a lot of objects and techniques for drawing in .NET, please refer to &lt;a href="http://msdn.microsoft.com/en-us/library/system.drawing.aspx"&gt;MSDN&lt;/a&gt; for more samples and documentation.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-527875060993257417?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/527875060993257417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=527875060993257417' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/527875060993257417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/527875060993257417'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/10/drawing-objects-in-net-c.html' title='Drawing objects in .NET (C#)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6651169294203701268</id><published>2008-10-24T15:43:00.000-07:00</published><updated>2008-10-24T17:21:55.850-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Encoding classes</title><content type='html'>&lt;em&gt;"Encoding is the process of transforming a set of Unicode characters into a sequence of bytes. In contrast, decoding is the process of transforming a sequence of encoded bytes into a set of Unicode characters."... (MSDN)&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;ASCIIEncoding&lt;/strong&gt;&lt;em&gt; (7-bit ASCII characters.  &lt;strong&gt;ATENTION&lt;/strong&gt;: this is NOT a 8-bit ASCII characters conversion!!!)&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;UTF7Encoding&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;UTF8Encoding&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;UnicodeEncoding&lt;/strong&gt;&lt;em&gt; (UTF-16)&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;UTF32Encoding&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

Here an example how to convert one string from Unicode to UTF-8 and back again.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Create a string that contains Unicode characters.&lt;/span&gt;
String unicodeString =
    &lt;span class="str"&gt;"This Unicode string contains two characters "&lt;/span&gt; +
    &lt;span class="str"&gt;"with codes outside the traditional ASCII code range, "&lt;/span&gt; +
    &lt;span class="str"&gt;"Pi (\u03a0) and Sigma (\u03a3)."&lt;/span&gt;;

MessageBox.Show(unicodeString);

&lt;span class="rem"&gt;// Getting unicode string converted to UTF-8 as bytes values&lt;/span&gt;
UTF8Encoding utf8Encoding = &lt;span class="kwrd"&gt;new&lt;/span&gt; UTF8Encoding();
Byte[] utf8Bytes = utf8Encoding.GetBytes(unicodeString);

&lt;span class="rem"&gt;// These bytes are ready for deliver them through a socket port (TCP/IP)&lt;/span&gt;
&lt;span class="rem"&gt;// or for convert them to one encoded base64 string&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; base64string = Convert.ToBase64String(utf8Bytes);
MessageBox.Show(base64string);

&lt;span class="rem"&gt;// Decode bytes back to string.&lt;/span&gt;
&lt;span class="rem"&gt;// Notice Pi and Sigma characters are still present.&lt;/span&gt;
String decodedString = utf8Encoding.GetString(utf8Bytes);
MessageBox.Show(decodedString);
&lt;/pre&gt;&lt;br&gt;

See also: &lt;br&gt;&lt;br&gt;

&lt;a href="http://olondono.blogspot.com/2008/01/conversion-between-ansi-and-unicode.html"&gt;Conversion between ANSI and Unicode&lt;/a&gt;&lt;br&gt;
&lt;a href="http://olondono.blogspot.com/2008/01/encrypting-and-decrypting-data.html"&gt;Encrypting and Decrypting Data&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6651169294203701268?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6651169294203701268/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6651169294203701268' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6651169294203701268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6651169294203701268'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/10/encoding.html' title='Encoding classes'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-3037360560365754776</id><published>2008-10-24T12:56:00.000-07:00</published><updated>2008-10-24T13:33:19.662-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><title type='text'>RegEx brief</title><content type='html'>For a complete explanation about using &lt;em&gt;Regular Expressions&lt;/em&gt; please take a look to &lt;a href="http://www.codeproject.com/KB/dotnet/regextutorial.aspx"&gt;this great article&lt;/a&gt; by &lt;strong&gt;Jim Hollenhorst&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;

You can use the &lt;a href="http://www.ultrapico.com/Expresso.htm"&gt;Expresso&lt;/a&gt; tool for build and test regular expressions.&lt;br&gt;&lt;br&gt;

Special characters:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;strong&gt;.&lt;/strong&gt;   Match any character except newline 
&lt;strong&gt;\w&lt;/strong&gt;  Match any alphanumeric character 
&lt;strong&gt;\s&lt;/strong&gt;  Match any whitespace character 
&lt;strong&gt;\d&lt;/strong&gt;  Match any digit 
&lt;strong&gt;\b&lt;/strong&gt;  Match the beginning or end of a word 
&lt;strong&gt;^&lt;/strong&gt;   Match the beginning of the string 
&lt;strong&gt;$&lt;/strong&gt;   Match the end of the string 
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

Repetitions:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;strong&gt;*&lt;/strong&gt;     Repeat any number of times 
&lt;strong&gt;+&lt;/strong&gt;     Repeat one or more times 
&lt;strong&gt;?&lt;/strong&gt;     Repeat zero or one time 
&lt;strong&gt;{n}&lt;/strong&gt;   Repeat n times 
&lt;strong&gt;{n,m}&lt;/strong&gt; Repeat at least n, but no more than m times 
&lt;strong&gt;{n,}&lt;/strong&gt;  Repeat at least n times 
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

Ranges samples:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;em&gt;[aeiou]&lt;/em&gt;  matches any vowel
&lt;em&gt;[.?!]&lt;/em&gt;    matches the punctuation
&lt;em&gt;[a-z0-9]&lt;/em&gt; match any lowercase letter of the alphabet, or any digit
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

Negations:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
\W       Match any character that is NOT alphanumeric 
\S       Match any character that is NOT whitespace 
\D       Match any character that is NOT a digit 
\B       Match a position that is NOT the beginning or end of a word 
[^x]     Match any character that is NOT x 
[^aeiou] Match any character that is NOT one of the characters aeiou 
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

Some samples &lt;em&gt;(there are a lot of best and optimal samples on Internet, look for them or use &lt;a href="http://www.ultrapico.com/Expresso.htm"&gt;Expresso &lt;/a&gt;to build them)&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;strong&gt;\b\d\d\d-\d\d\d\d&lt;/strong&gt;     Find seven-digit phone number
&lt;strong&gt;\b\d{3}-\d{4}&lt;/strong&gt;         Find seven-digit phone number a better way
&lt;strong&gt;^\d{3}-\d{4}$&lt;/strong&gt;         Validate a seven-digit phone number
&lt;strong&gt;\d{3}-\d{2}-\d{4}&lt;/strong&gt;     Social security number
&lt;br&gt;&lt;br&gt;
&lt;strong&gt;\ba\w*\b&lt;/strong&gt;              Find words that start with the letter a
&lt;strong&gt;\b\w{6}\b&lt;/strong&gt;             Find six letter words
&lt;strong&gt;\b\w{5,6}\b&lt;/strong&gt;           Find all five and six letter words
&lt;br&gt;&lt;br&gt;
&lt;strong&gt;(\d{1,3}\.){3}\d{1,3}&lt;/strong&gt; A simple IP address finder
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

For more information about grouping, positive and negative lookarounds, Greedy and Lazy, please please take a look to &lt;a href="http://www.codeproject.com/KB/dotnet/regextutorial.aspx"&gt;this great article&lt;/a&gt; by &lt;strong&gt;Jim Hollenhorst&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3037360560365754776?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3037360560365754776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3037360560365754776' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3037360560365754776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3037360560365754776'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/10/regex-brief.html' title='RegEx brief'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-7755315643844069183</id><published>2008-10-15T19:03:00.000-07:00</published><updated>2008-10-16T11:54:37.258-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Finally Certified !!!</title><content type='html'>Yahooo,&lt;br&gt;&lt;br&gt;

Finally I finished my DAX certification, &lt;strong&gt;Microsoft Certified Business Management Solutions Professional - Development for Microsoft Dynamics AX.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;a href="http://2.bp.blogspot.com/_klu-RAVtjKg/SPeNqv1yc1I/AAAAAAAAACI/4AYPbI8D5G8/s1600-h/DynamicsP(rgb)_1074.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_klu-RAVtjKg/SPeNqv1yc1I/AAAAAAAAACI/4AYPbI8D5G8/s320/DynamicsP(rgb)_1074.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5257826855514436434" /&gt;&lt;/a&gt;

Now, looking for a job here in &lt;strong&gt;Montreal, Canada&lt;/strong&gt;.  If someone knows where can I apply, please write me a comment.&lt;br&gt;&lt;br&gt;

Tks&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-7755315643844069183?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/7755315643844069183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=7755315643844069183' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7755315643844069183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7755315643844069183'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/10/finally-certified.html' title='Finally Certified !!!'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_klu-RAVtjKg/SPeNqv1yc1I/AAAAAAAAACI/4AYPbI8D5G8/s72-c/DynamicsP(rgb)_1074.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-7962546194395060500</id><published>2008-08-26T07:02:00.000-07:00</published><updated>2008-08-26T08:09:42.862-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>How to print a different Sales Invoice per company in AX</title><content type='html'>If you want to print a different &lt;em&gt;Sales Invoice&lt;/em&gt; per every company you have, you must change the method &lt;strong&gt;printJournal&lt;/strong&gt; in the table &lt;em&gt;CustInvoiceJour&lt;/em&gt; and the form &lt;em&gt;CustInvoiceJournal&lt;/em&gt; (MenuButton "SalesInvoiceShow" -&gt; Copy, Original and Original print):&lt;br&gt;&lt;br&gt;

Modified method &lt;em&gt;printJournal&lt;/em&gt; for the table &lt;em&gt;CustInvoiceJour&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
server &lt;span class="kwrd"&gt;void&lt;/span&gt;  printJournal(SalesFormLetter      salesFormLetter = &lt;span class="kwrd"&gt;null&lt;/span&gt;,
                          RecordSortedList     journalList     = &lt;span class="kwrd"&gt;null&lt;/span&gt;,
                          NoYes                copy            = NoYes::No)
{
    Args                parameters = &lt;span class="kwrd"&gt;new&lt;/span&gt; Args();
    MenuFunction        salesInvoiceMenu;
    ;

    &lt;span class="rem"&gt;// Show the correct report for the every company&lt;/span&gt;
    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (strupr(curExt()))
    {
        &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"OPP"&lt;/span&gt;:
            salesInvoiceMenu = &lt;span class="kwrd"&gt;new&lt;/span&gt; MenuFunction(menuitemoutputstr(OPPSalesInvoice),MenuItemType::Output);
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
        
        &lt;span class="kwrd"&gt;default&lt;/span&gt;:
            salesInvoiceMenu = &lt;span class="kwrd"&gt;new&lt;/span&gt; MenuFunction(menuitemoutputstr(SalesInvoice),MenuItemType::Output);
    }
    &lt;span class="rem"&gt;// End&lt;/span&gt;

    parameters.caller(salesFormLetter);

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (journalList)
        parameters.&lt;span class="kwrd"&gt;object&lt;/span&gt;(journalList);
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        parameters.record(&lt;span class="kwrd"&gt;this&lt;/span&gt;);

    salesInvoiceMenu.run(parameters);
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

For every MenuItemButton below the &lt;em&gt;SalesInvoiceShow&lt;/em&gt;, you must override the clicked method as follows:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; clicked()
{
    Args                parameters = &lt;span class="kwrd"&gt;new&lt;/span&gt; Args();
    MenuFunction        salesInvoiceMenu;
    ;

    &lt;span class="rem"&gt;// Let the menuItemButton as this, with original parameters but&lt;/span&gt;
    &lt;span class="rem"&gt;// don't call super, to avoid call directly the report SalesInvoice&lt;/span&gt;
    &lt;span class="rem"&gt;//super();&lt;/span&gt;

    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (strupr(curExt()))
    {
        &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"OPP"&lt;/span&gt;:
            salesInvoiceMenu = &lt;span class="kwrd"&gt;new&lt;/span&gt; MenuFunction(menuitemoutputstr(OPPSalesInvoiceCopy),MenuItemType::Output);
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;

        &lt;span class="kwrd"&gt;default&lt;/span&gt;:
            salesInvoiceMenu = &lt;span class="kwrd"&gt;new&lt;/span&gt; MenuFunction(menuitemoutputstr(SalesInvoiceCopy),MenuItemType::Output);
    }

    parameters.caller(&lt;span class="kwrd"&gt;this&lt;/span&gt;);
    parameters.record(CustInvoiceJour);

    salesInvoiceMenu.run(parameters);
    &lt;span class="rem"&gt;// End&lt;/span&gt;
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; You must use &lt;em&gt;SalesInvoiceCopy, SalesInvoiceOriginal and SalesInvoice&lt;/em&gt; por &lt;em&gt;Copy, Original and Original print&lt;/em&gt; respectively.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-7962546194395060500?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/7962546194395060500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=7962546194395060500' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7962546194395060500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7962546194395060500'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/how-to-print-different-sales-invoice.html' title='How to print a different Sales Invoice per company in AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2983817043840663075</id><published>2008-08-12T10:24:00.000-07:00</published><updated>2008-08-12T10:37:46.190-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='Source Code'/><title type='text'>Rounding in AX (real to integer)</title><content type='html'>How to perform a successful round in AX from real to integer?... &lt;br&gt;
Well, the answer is: &lt;em&gt;use the function &lt;strong&gt;decround&lt;/strong&gt;&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Job1(Args _args)
{
    &lt;span class="kwrd"&gt;int&lt;/span&gt; i, ii;
    real r = 334.55, r2 = 334.14;
    ;

    i = decround(r, 0);
    ii = decround(r2, 0);

    &lt;span class="rem"&gt;// It shows 335, 334&lt;/span&gt;
    info(strfmt(&lt;span class="str"&gt;"%1, %2"&lt;/span&gt;, i, ii));
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2983817043840663075?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2983817043840663075/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2983817043840663075' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2983817043840663075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2983817043840663075'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/rounding-in-ax-real-to-integer.html' title='Rounding in AX (real to integer)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8085868879724481304</id><published>2008-08-08T07:27:00.000-07:00</published><updated>2008-08-08T07:44:20.394-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Dynamics AX 2009 - Installation</title><content type='html'>Here are the links for downloading Dynamics AX 2009 and its demo data.  (Customer logon required).&lt;br&gt;&lt;br&gt;

&lt;a href="https://mbs.microsoft.com/customersource/downloads/servicepacks/dynamicsax2009release.htm?printpage=false"&gt;https://mbs.microsoft.com/customersource/downloads/servicepacks/dynamicsax2009release.htm?printpage=false&lt;/a&gt;&lt;br&gt;&lt;br&gt;

&lt;a href="https://mbs.microsoft.com/customersource/downloads/servicepacks/AX2009DemoData.htm"&gt;https://mbs.microsoft.com/customersource/downloads/servicepacks/AX2009DemoData.htm&lt;/a&gt;&lt;br&gt;&lt;br&gt;

Download the database backup either with transactions or without them.  But this method provides you with a demo license until june 9th, 2009.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;First impressions:&lt;/strong&gt;&lt;br&gt;&lt;br&gt; 

The same core from Dynamics AX 4.0 but improved with a good additions like Workflow for example.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8085868879724481304?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8085868879724481304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8085868879724481304' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8085868879724481304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8085868879724481304'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/dynamics-ax-2009-installation.html' title='Dynamics AX 2009 - Installation'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8148053180505564247</id><published>2008-08-04T19:39:00.000-07:00</published><updated>2009-07-04T18:40:21.847-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Running batch jobs automatically in Dynamics AX</title><content type='html'>For learning how to create and launch batch jobs in Dynamics AX, please take a look to all topics in &lt;a href="http://msdn.microsoft.com/en-us/library/aa549082(AX.10).aspx"&gt;http://msdn.microsoft.com/en-us/library/aa549082(AX.10).aspx&lt;/a&gt;.&lt;br&gt;&lt;br&gt;

If we want to configure an automatic &lt;em&gt;batch job server&lt;/em&gt;, we need to modify the class &lt;em&gt;SysStartupCmdBatchRun&lt;/em&gt;, method &lt;em&gt;infoRun&lt;/em&gt;, as follows:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; infoRun()
{
    batchRun batchRun = &lt;span class="kwrd"&gt;new&lt;/span&gt; batchRun();
    ;

    batchRun.parmUseForm(&lt;span class="kwrd"&gt;true&lt;/span&gt;);
    batchRun.parmGroupId(parm); &lt;span class="rem"&gt;// added&lt;/span&gt;
    batchRun.run();
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

And for a batch group named &lt;em&gt;"myGroup"&lt;/em&gt; for example, we can use the &lt;em&gt;Microsoft Dynamics AX Configuration Utility&lt;/em&gt; to specify the &lt;em&gt;"Command to run at application startup:"&lt;/em&gt; as &lt;strong&gt;Batch_myGroup&lt;/strong&gt;.  This enable the AX client to run every batch job in this group.&lt;br&gt;&lt;br&gt;

&lt;img src="http://lh5.ggpht.com/_klu-RAVtjKg/SJfAo4fqYMI/AAAAAAAAAAU/dEek8fDYBKs/s400/BatchParameter_AX.jpg"&gt;&lt;br&gt;&lt;br&gt;

We can also use the command line as &lt;em&gt;{path}\ax32.exe startupcmd=batch_myGroup&lt;/em&gt;.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8148053180505564247?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8148053180505564247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8148053180505564247' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8148053180505564247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8148053180505564247'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/running-batch-jobs-automatically-in.html' title='Running batch jobs automatically in Dynamics AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_klu-RAVtjKg/SJfAo4fqYMI/AAAAAAAAAAU/dEek8fDYBKs/s72-c/BatchParameter_AX.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-7469299315113410993</id><published>2008-08-04T17:46:00.000-07:00</published><updated>2008-08-04T19:20:21.428-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Creating a batch class in Dynamics AX</title><content type='html'>For creating a batch class in Dynamics AX we can start from the Tutorial_RunbaseBatch class, but here is the explanation for understanding all its methods:&lt;br&gt;&lt;br&gt;

In the &lt;em&gt;classDeclaration&lt;/em&gt;, we declare any variable that contains user's selection or preferences (for example, the customer account for launch a customer report).  Also, we declare other variables like dialog fields, auxiliar variables, etc.  But, the most important feature here, is the &lt;em&gt;#localmacro.CurrentList&lt;/em&gt; declaration. This macro helps you to define which variables you want to save for running the class in batch mode (when not user interaction is available).&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;class&lt;/span&gt; Tutorial_RunbaseBatch extends RunBaseBatch
{
    &lt;span class="rem"&gt;// Packed variables&lt;/span&gt;
    TransDate       transDate;
    CustAccount     custAccount;

    &lt;span class="rem"&gt;// Dialog fields&lt;/span&gt;
    DialogField     dlgCustAccount;
    DialogField     dlgTransDate;

    &lt;span class="rem"&gt;// Current version&lt;/span&gt;
    &lt;span class="rem"&gt;// We can have different versions for different purposes&lt;/span&gt;
    #define.CurrentVersion(1)
    #define.Version1(1)
    #localmacro.CurrentList  &lt;span class="rem"&gt;// Our current variable list for save user's selected values&lt;/span&gt;
        transDate,
        custAccount
    #endmacro
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

The macro &lt;em&gt;#define.CurrentVersion(1)&lt;/em&gt; and &lt;em&gt;#define.Version1(1)&lt;/em&gt; are useful for scaling our class when we need to change/upgrade it preserving compatibility.&lt;br&gt;&lt;br&gt;

Now two methods: &lt;em&gt;pack&lt;/em&gt; and &lt;em&gt;unpack&lt;/em&gt;.  These methods are used for store and retrieve user's preferences and perform the batch operation when none user are available (in batch mode).  Here is the point where we use the macro defined previously:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;container&lt;/span&gt; pack()
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; [#CurrentVersion,#CurrentList];
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; boolean unpack(&lt;span class="kwrd"&gt;container&lt;/span&gt; packedClass)
{
    Version version = RunBase::getVersion(packedClass);
;
    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (version)
    {
        &lt;span class="kwrd"&gt;case&lt;/span&gt; #CurrentVersion:
            [version,#CurrentList] = packedClass;
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
        &lt;span class="rem"&gt;//case #otherVersion:&lt;/span&gt;
            &lt;span class="rem"&gt;//[version,#CurrentList, #otherList] = packedClass;&lt;/span&gt;
            &lt;span class="rem"&gt;//break;&lt;/span&gt;
        &lt;span class="kwrd"&gt;default&lt;/span&gt;:
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }

    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

Bacause we need to ask the user about preferences for run this object (report, process, query, etc.), we must implement some methods: &lt;br&gt;&lt;br&gt;

- &lt;em&gt;dialog&lt;/em&gt;: for build the custom dialog for prompting user's preferences.&lt;br&gt;
- &lt;em&gt;dialogPostRun&lt;/em&gt;: after dialog was created, you can perform other UI tasks here.&lt;br&gt;
- &lt;em&gt;getFromDialog&lt;/em&gt;: used for retrive user's preferences (dialog values).&lt;br&gt;
- &lt;em&gt;validate&lt;/em&gt;: here, you can perform a validation for any data entered by the user.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; Object dialog()
{
    DialogRunbase       dialog = super();
    ;
 
    &lt;span class="rem"&gt;// Creation of our custom dialog fields/controls to ask user for preferences&lt;/span&gt;
    dlgTransDate = dialog.addFieldValue(typeid(TransDate),transDate);
    dlgCustAccount = dialog.addFieldValue(typeid(CustAccount),custAccount);

    &lt;span class="kwrd"&gt;return&lt;/span&gt; dialog;
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; dialogPostRun(DialogRunbase dialog)
{
;
    super(dialog);
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; boolean getFromDialog()
{
    ;

    &lt;span class="rem"&gt;// Retrieving user's preferences&lt;/span&gt;
    transDate   = dlgTransDate.&lt;span class="kwrd"&gt;value&lt;/span&gt;();
    custAccount = dlgCustAccount.&lt;span class="kwrd"&gt;value&lt;/span&gt;();

    &lt;span class="kwrd"&gt;return&lt;/span&gt; super();
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; boolean validate()
{
    &lt;span class="rem"&gt;// We can perform some validations here&lt;/span&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;false&lt;/span&gt;)
        &lt;span class="kwrd"&gt;return&lt;/span&gt; checkFailed(&lt;span class="str"&gt;""&lt;/span&gt;);

    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
}
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

Finally, the &lt;em&gt;main&lt;/em&gt; method &lt;em&gt;constructs&lt;/em&gt; the object from this batch class, and after prompting user and validation was successful, the &lt;em&gt;run&lt;/em&gt; method is called to perform some task (in batch mode if it was selected):&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
server &lt;span class="kwrd"&gt;static&lt;/span&gt; Tutorial_RunbaseBatch construct()
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Tutorial_RunbaseBatch();
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; run()
{
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        &lt;span class="rem"&gt;// Obviously, this code is silly, why show something to nobody?&lt;/span&gt;
        &lt;span class="rem"&gt;// remember, this code is running in batch without user interaction&lt;/span&gt;
        info(strfmt(&lt;span class="str"&gt;"Parameters: %1 for %2"&lt;/span&gt;, transDate, custAccount));
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt;(Exception::Deadlock)
    {
        retry;
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt;(Exception::UpdateConflict)
    {
        &lt;span class="kwrd"&gt;throw&lt;/span&gt; Exception::UpdateConflict;
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt;
    {
        &lt;span class="kwrd"&gt;throw&lt;/span&gt; Exception::Error;
    }
}

&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; main(Args args)
{
    Tutorial_RunbaseBatch    tutorial_RunBase;
    ;

    &lt;span class="rem"&gt;// Instanciating this batch class&lt;/span&gt;
    tutorial_RunBase = Tutorial_RunbaseBatch::construct();

    &lt;span class="rem"&gt;// Prompting user and run if all is ok&lt;/span&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (tutorial_RunBase.prompt())
        tutorial_RunBase.run();
}
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-7469299315113410993?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/7469299315113410993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=7469299315113410993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7469299315113410993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7469299315113410993'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/creating-batch-class-in-dynamics-ax.html' title='Creating a batch class in Dynamics AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8768012672592809918</id><published>2008-08-04T16:43:00.000-07:00</published><updated>2008-08-04T17:14:21.327-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Using ADO for interfacing AX with an external database</title><content type='html'>If we need to interface any external database with Dynamics AX, we can achieve this task by using ADO and its AX available classes: &lt;em&gt;CCADOConnection, CCADORecordSet, CCADOFields, CCADOField&lt;/em&gt; and &lt;em&gt;CCADOCommand&lt;/em&gt;.  Here an example:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ADOTestJob(Args _args)
{
    CCADOConnection     ccConnection;
    CCADOCommand        ccCommand;
    CCADORecordSet      ccRecordset;
    CCADOFields         ccFields;
    str                 st;
    str                 data1;
    &lt;span class="kwrd"&gt;int&lt;/span&gt;                 data2;
    ;

    ccConnection = &lt;span class="kwrd"&gt;new&lt;/span&gt; CCADOConnection();

    &lt;span class="rem"&gt;// Setting the connection string&lt;/span&gt;
    ccConnection.connectionString(StrFmt(&lt;span class="str"&gt;'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=%3;Password=%4;Initial Catalog=%2;Data Source=%1'&lt;/span&gt;
            , &lt;span class="str"&gt;'servername'&lt;/span&gt;  &lt;span class="rem"&gt;// Server's IP or name&lt;/span&gt;
            , &lt;span class="str"&gt;'database'&lt;/span&gt;    &lt;span class="rem"&gt;// Database or catalog&lt;/span&gt;
            , &lt;span class="str"&gt;'user'&lt;/span&gt;        &lt;span class="rem"&gt;// Username&lt;/span&gt;
            , &lt;span class="str"&gt;'pwd'&lt;/span&gt;         &lt;span class="rem"&gt;// Password&lt;/span&gt;
            ));

    &lt;span class="rem"&gt;// Open the connection&lt;/span&gt;
    ccConnection.open();

    &lt;span class="rem"&gt;// Preparing the query&lt;/span&gt;
    st = &lt;span class="str"&gt;"SELECT * FROM mytable"&lt;/span&gt;;

    &lt;span class="rem"&gt;// Recordset object creation&lt;/span&gt;
    ccRecordset = &lt;span class="kwrd"&gt;new&lt;/span&gt; CCADORecordSet();

    &lt;span class="rem"&gt;// Executing the query&lt;/span&gt;
    ccRecordset.open( st, ccConnection );

    &lt;span class="rem"&gt;// Reading data&lt;/span&gt;
    &lt;span class="kwrd"&gt;while&lt;/span&gt; (!ccRecordset.EOF())
    {
        ccFields = ccRecordset.fields();
        
        &lt;span class="rem"&gt;// We can access fields either by name or by Index&lt;/span&gt;
        data1 = ccFields.itemName(&lt;span class="str"&gt;"FIELD1"&lt;/span&gt;).&lt;span class="kwrd"&gt;value&lt;/span&gt;();
        data2 = ccFields.itemIdx(1).&lt;span class="kwrd"&gt;value&lt;/span&gt;();

        info(strfmt(&lt;span class="str"&gt;"Data %1, %2"&lt;/span&gt;, data1, data2));
        
        &lt;span class="rem"&gt;// Read next record&lt;/span&gt;
        ccRecordset.moveNext();
    }

    &lt;span class="rem"&gt;// Closing the connection&lt;/span&gt;
    ccRecordset.close();
    ccConnection.close();
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

If we need to execute something (an &lt;em&gt;UPDATE&lt;/em&gt;, &lt;em&gt;DELETE&lt;/em&gt;, etc.), we can use the &lt;em&gt;CCADOCommand&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; ExecuteSQLExt(str sql)
{
    &lt;span class="rem"&gt;// Creating the ADO Command object&lt;/span&gt;
    ccCommand = &lt;span class="kwrd"&gt;new&lt;/span&gt; CCADOCommand();

    &lt;span class="rem"&gt;// Associate it with an existing opened connection&lt;/span&gt;
    ccCommand.activeConnection(ccConnection);

    &lt;span class="rem"&gt;// Executing the command&lt;/span&gt;
    ccCommand.commandText(SQL);

    ccCommand.execute();
}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

NOTE: For working with ADO constants like cursor types (&lt;em&gt;adOpenForwardOnly, adOpenKeyset, adOpenDynamic, adOpenStatic&lt;/em&gt;), we only need to include the macro CCADO (#CCADO) where they are defined.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8768012672592809918?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8768012672592809918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8768012672592809918' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8768012672592809918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8768012672592809918'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/using-ado-for-interfacing-ax-with_04.html' title='Using ADO for interfacing AX with an external database'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-540044300602470350</id><published>2008-08-04T09:39:00.000-07:00</published><updated>2008-08-04T09:45:03.040-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>SQL 2005 to Linked SQL Server 7.0/2000 error</title><content type='html'>If you get this error trying to access a linked server (7.0/2000) from an SQL 2005 64-bits:&lt;br&gt;&lt;br&gt;

&lt;em&gt;The stored procedure required to complete this operation could not be found on the server. Please contact your system administrator. 
Msg 7311, Level 16, State 2, Line 1 
Cannot obtain the schema rowset "DBSCHEMA_TABLES_INFO" for OLE DB provider "SQLNCLI" for linked server "&amp;lt;LinkedServerName&amp;gt;". The provider supports the interface, but returns a failure code when it is used. &lt;/em&gt;&lt;br&gt;&lt;br&gt;

It is probable that the linked server is missing the stored procedure &lt;em&gt;"sp_tables_info_rowset_64"&lt;/em&gt;, so, run the following script for the master database:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;PROCEDURE&lt;/span&gt; [sp_tables_info_rowset_64] 
@table_name sysname, 
@table_schema sysname = &lt;span class="kwrd"&gt;NULL&lt;/span&gt;, 
@table_type nvarchar(255) = &lt;span class="kwrd"&gt;null&lt;/span&gt; 
&lt;span class="kwrd"&gt;AS&lt;/span&gt; 
&lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;Result&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;
&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @&lt;span class="kwrd"&gt;Result&lt;/span&gt; = 0

&lt;span class="kwrd"&gt;EXEC&lt;/span&gt; @&lt;span class="kwrd"&gt;Result&lt;/span&gt; = sp_tables_info_rowset @table_name, @table_schema, @table_type 
GO&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

More information: 
&lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;906954"&gt;http://support.microsoft.com/default.aspx?scid=kb;en-us;906954&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-540044300602470350?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/540044300602470350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=540044300602470350' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/540044300602470350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/540044300602470350'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/sql-2005-to-linked-sql-server-702000.html' title='SQL 2005 to Linked SQL Server 7.0/2000 error'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4547799019677240288</id><published>2008-08-03T17:41:00.000-07:00</published><updated>2008-08-03T19:33:57.913-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Tips for Upgrade Axapta 3.0 to Dynamics AX 4.0</title><content type='html'>- Be careful with table's conversion.  If you had modified methods or fields, is probable that table will be converted losing functionality like standard methods, delete actions, indexes, fields, etc.  &lt;br&gt;&lt;br&gt;

For example, when we converted the &lt;em&gt;VendTable&lt;/em&gt;, the field &lt;em&gt;CountryId&lt;/em&gt; wasn't properly converted (renamed as &lt;em&gt;CountryRegionId&lt;/em&gt;) because we had modifications in this field and a lot of compilation errors was raised, so, we removed all modifications before upgrade this table to AX 4.0, then, we applied all changes before make the database conversion.&lt;br&gt;&lt;br&gt;

To ensure a successful conversion, you need to compare every modified table between your layer (CUS, VAR, etc.) and any system layer (SYS, SYP, etc.) Verifying that you are not losing fields, indexes, methods, delete actions, etc.&lt;br&gt;&lt;br&gt;

- Forms must be converted manually because you can lose a lot of functionality.  You can use this tip: make the upgrade not matter about errors, then make a copy of the converted form, delete your custom layer (CUS, VAR, etc.) and use &lt;em&gt;drag and drop&lt;/em&gt; to pass controls and methods from the copied form to the standard form until you complete the customization you want to have.&lt;br&gt;&lt;br&gt;

Don't forget to compare layers to avoid losing of standard functionality, specially with methods and events.&lt;br&gt;&lt;br&gt;

- Reports has changed in architecture.  In Axapta 3.0 you had an auxiliar/helper class that was responsible for prompting query's values and other tasks.  In AX 4.0, that functionality was included inside the class &lt;em&gt;Report&lt;/em&gt;, so you need to pass manually any change made in reports preserving the new architecture.&lt;br&gt;&lt;br&gt;

- &lt;em&gt;RecIds&lt;/em&gt; are now long integers (64-bits).  Any field or EDT that references &lt;em&gt;RecIds&lt;/em&gt; must be converted to 64-bits.&lt;br&gt;&lt;br&gt;

- Left justified fields offers a better performance with SQL Server 2005.&lt;br&gt;&lt;br&gt;

- If you have a partner's logon, read the following article: &lt;a href="https://mbs.microsoft.com/customersource/documentation/whitepapers/AX40_UpgradeOptimization_SQL"&gt;https://mbs.microsoft.com/customersource/documentation/whitepapers/AX40_UpgradeOptimization_SQL&lt;/a&gt;&lt;br&gt;&lt;br&gt;

- Fix &lt;em&gt;tempdb&lt;/em&gt; and &lt;em&gt;MaxDegree for Parallelism&lt;/em&gt; as explained in 
&lt;a href="http://blogs.msdn.com/axperf/archive/2008/03/10/welcome-database-configuration-checklist-part-1.aspx"&gt;http://blogs.msdn.com/axperf/archive/2008/03/10/welcome-database-configuration-checklist-part-1.aspx&lt;/a&gt;&lt;br&gt;&lt;br&gt;

- Execute &lt;em&gt;AxDbUpgrade.exe&lt;/em&gt; using the &lt;strong&gt;/P #&lt;/strong&gt; parameter (where # = number of physical processors)&lt;br&gt;&lt;br&gt;

- You are going to lose some permissions and groups.  Take your time for rebuild them.&lt;br&gt;&lt;br&gt;

- OLAP configuration for SQL Server 2005 is required.  See my other post 
&lt;a href="http://olondono.blogspot.com/2008/08/configuring-analysis-services-2005-for.html"&gt;Configuring Analysis Services 2005 for AX&lt;/a&gt; for details.&lt;br&gt;&lt;br&gt;

- Sending e-mails from a client using Windows Vista could raise an error.  You must use an Outlook 2007 client.&lt;br&gt;&lt;br&gt;

More details in &lt;a href="http://olondono.blogspot.com/2008/08/experiences-upgrading-axapta-30-to.html"&gt;Experiences upgrading Axapta 3.0 to Dynamics AX 4.0&lt;/a&gt;&lt;br&gt;&lt;br&gt;

- Follow the upgrade flowchart step by step:&lt;br&gt;&lt;br&gt;

&lt;a href="http://bp3.blogger.com/_klu-RAVtjKg/SJZliISjJWI/AAAAAAAAAAM/b_yxV6GQXgU/s1600-h/Flowchart.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_klu-RAVtjKg/SJZliISjJWI/AAAAAAAAAAM/b_yxV6GQXgU/s320/Flowchart.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5230479654252651874" /&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4547799019677240288?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4547799019677240288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4547799019677240288' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4547799019677240288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4547799019677240288'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/tips-for-upgrade-axapta-30-to-dynamics.html' title='Tips for Upgrade Axapta 3.0 to Dynamics AX 4.0'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_klu-RAVtjKg/SJZliISjJWI/AAAAAAAAAAM/b_yxV6GQXgU/s72-c/Flowchart.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8599398799829564005</id><published>2008-08-03T12:04:00.000-07:00</published><updated>2008-08-03T19:06:59.967-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Experiences upgrading Axapta 3.0 to Dynamics AX 4.0</title><content type='html'>Some notes from my experience upgrading Axapta 3.0 to Dynamics AX 4.0 in Transportes Botero Soto, Colombia.&lt;br&gt;&lt;br&gt;

- Any modification in system classes must be removed before make the upgrade.  After that, you can apply changes manually.  (ex. &lt;a href="http://olondono.blogspot.com/2007/08/avoiding-users-to-open-more-than-one.html"&gt;Avoiding users to open more than one session in Axapta (Dynamics AX)&lt;/a&gt;)&lt;br&gt;&lt;br&gt;

- In Axapta 3.0, we had created a &lt;em&gt;CustomerRef&lt;/em&gt; field in the &lt;em&gt;SalesLine&lt;/em&gt; table.  In AX, this field was created by Microsoft.  So, to avoid conflict, we need delete it before perform the AOT conversion.&lt;br&gt;&lt;br&gt;

- For releasing disk space, we can delete data in tables like &lt;em&gt;sysDatabaseLog, sysUserLog, axOldRecIds, axOldToNewRecIds, OlapAmount&lt;/em&gt;.  Also, we can truncate the transaction log before conversion. See &lt;a href="http://olondono.blogspot.com/2007/08/how-to-truncate-any-databases-log-file.html"&gt;How to truncate any Database's log file&lt;/a&gt;.&lt;br&gt;&lt;br&gt;

- The class &lt;em&gt;ledgerJournal&lt;/em&gt; not exist anymore in AX 4.0 and if you are using it for generate a ledger journal number, you must change the code &lt;em&gt;ledgerJournal.newJournalNum(true);&lt;/em&gt; by &lt;em&gt;NumberSeq::newGetNum(LedgerParameters::numRefJournalNum(), true).num();&lt;/em&gt;&lt;br&gt;&lt;br&gt;

- The class &lt;em&gt;Specification&lt;/em&gt; was changed in 4.0.  Now, we must set the reference table id parameter.&lt;br&gt;&lt;br&gt;
  
&amp;nbsp;&amp;nbsp;- Instancing before: &lt;em&gt;specification = new Specification_OffsetVoucher(vendTable.tableId, vendTable.recId);&lt;/em&gt; now, &lt;em&gt;specification = Specification::construct(SpecType::OffsetVoucher, vendTable.tableId, vendTable.recId); &lt;/em&gt;&lt;br&gt;&lt;br&gt;
 
&amp;nbsp;&amp;nbsp;- For the specification creation now we must include the table's id: &lt;em&gt;specification.create(vendSettlement.TableId, vendSettlement.recId, vendSettlement.settleAmountCur, _vendTrans.currencyCode);&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;- For delete one specification (marked open transactions), before: &lt;em&gt;specification.deleteTransact()&lt;/em&gt; and now &lt;em&gt;specification.deleteSpecifications()&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;- The field &lt;em&gt;specTrans.RefId&lt;/em&gt; not exist anymore, now it is called &lt;em&gt;RefRecId&lt;/em&gt; and also, we must set the field &lt;em&gt;RefTableId&lt;/em&gt;.

- &lt;em&gt;RecIds&lt;/em&gt; in AX 4.0 are long-integers (64-bits), for that reason, any assignment with an integer variable will lose precision/accuracy, so we must ensure that any custom field related to &lt;em&gt;RecIds&lt;/em&gt;, is large as 64-bits.&lt;br&gt;&lt;br&gt;

- If we have &lt;em&gt;modified Forms&lt;/em&gt; in Axapta 3.0, we must make the conversion manually, we can use this technique for optimize the copy of tabs, controls, buttons, methods, etc.  Duplicate the converted form, delete it from the custom layer (in our case: CUS), then use &lt;em&gt;drag and drop&lt;/em&gt; for any custom control and owner method.&lt;br&gt;&lt;br&gt;

- Good coding practices make easiest the conversion:&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp; - Put comments at the starting and ending block of source code modified (//Ini TBS … // End TBS…) and always try to write a good explaination for reasons you had made the change (that is not obvious for anyone different than you).&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp; - Use braces "{}" to identify correctly blocks of source code, no matter if the instruction only takes one line.  This provide a good "eagle view" for any change and inherent logic, avoiding waste of time.&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp; - Use spaces with assignment or logic operators ("x = y" instead of "x=y").  Again, this provide an "eagle view" because the brain doesn't need to separate every instruction's member.&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp; - Use four (4) spaces indentation (recommended).&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp; - Use parenthesis "()" when logic instructions comes, ex. &lt;em&gt;if (x==y &amp;&amp; z!=w || x!=w&lt;/em&gt; is less visible than &lt;em&gt;if ( (x == y) &amp;&amp; (z != w) || (x != w))&lt;/em&gt; … in the last one, you can identify operators quickly.&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp; - Use two or more lines for "select" instructions putting the "index", the "where" and logic instructions in their own indented line.  This show the real objective of the "select" instruction.&lt;br&gt;&lt;br&gt;

- When we need to hide/remove an user control, the best choice is doing it by code (&lt;em&gt;element.control.visible(false);&lt;/em&gt;).&lt;br&gt;&lt;br&gt;

- If you need to change standard code, you must enclosed it with comments and work with a copy to avoid lose of tracing.&lt;br&gt;&lt;br&gt;

- Any custom menu must be added manually, to avoid lose of properties like icon, help text, ext.&lt;br&gt;&lt;br&gt;

- &lt;em&gt;EDTs&lt;/em&gt; in version 4.0 should be left aligned instead of right aligned like in version 3.0.  You must review custom tables to get a better performance from SQL Server.&lt;br&gt;&lt;br&gt;

- Reference to non-existing labels can be found looking from the root node every item that contents data like "@GLxxxx".&lt;br&gt;&lt;br&gt;

- If you need to change a base enum, the new items can produce conflicts with new standard items in future versions.  To avoid this, you can set the value for new custom items starting from a none typical value like 50, 51, 52, etc.&lt;br&gt;&lt;br&gt;

- In the conversion, post-syncrhonization, if you get an error from &lt;em&gt;SalesTable&lt;/em&gt; and &lt;em&gt;SalesLine&lt;/em&gt; (fields &lt;em&gt;ShippingDateRequested&lt;/em&gt; and &lt;em&gt;ShippingDateConfirmed&lt;/em&gt;), is probable that you have records in &lt;em&gt;SalesTable&lt;/em&gt; without lines in &lt;em&gt;SalesLines&lt;/em&gt;.  Then, you need to remove that records.&lt;br&gt;&lt;br&gt;

- The upgrade process for the database could raise an error with the table &lt;em&gt;AxOldToNewRecIds&lt;/em&gt;.  In several groups, I found that this table can be deleted without problem.  After upgrade, you can copy the table manually.&lt;br&gt;&lt;br&gt;

- If you have SQL Server 2005 for Axapta 3.0, it is probable that you get some errors with &lt;em&gt;SysDiagrams&lt;/em&gt; and &lt;em&gt;dt.Properties&lt;/em&gt;.  You can delete those objects before use the tool &lt;em&gt;AxDBUpgrade&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

- You got the error: &lt;em&gt;Insufficient rights to execute Method … &lt;/em&gt;: you must delete all data from &lt;em&gt;SysConfig&lt;/em&gt; table (license data table).  It will be filled with the correct licenses code when needed.&lt;br&gt;&lt;br&gt;

- &lt;em&gt;Invalid license code for this language&lt;/em&gt;.  If you have a license for a language different than english, you need to change the value "en-us" by the correct value (ex. "es") for the &lt;em&gt;Administrator&lt;/em&gt; user. (Tables dbo.USERINFO and dbo.SYSUSERINFO)&lt;br&gt;&lt;br&gt;

- Error synchronizing the table &lt;em&gt;SalesParmTable&lt;/em&gt; because it has duplicated keys.  This is an "intermediated" table, so, you can delete its contents(?).&lt;br&gt;&lt;br&gt;

- Synchronization error: &lt;em&gt;"The total, internal size of the records in your joined SELECT statement is 26208 bytes, but Microsoft Dynamics is by default performance-tuned not to exceed 24576 bytes."&lt;/em&gt;  You need to specify a bigger value in the tab 'SQL in the &lt;em&gt;Dynamics AX Server Configuration&lt;/em&gt; tool (Administrative tools). My upgrade value was 49152.&lt;br&gt;&lt;br&gt;

- If you have custom fields in tables &lt;em&gt;smmQuotationLine&lt;/em&gt; and &lt;em&gt;smmQuotationTable&lt;/em&gt;, you need to change the code in the class &lt;em&gt;ReleaseUpdateDB39_Smm&lt;/em&gt; to include all custom fields when upgrading data.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8599398799829564005?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8599398799829564005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8599398799829564005' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8599398799829564005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8599398799829564005'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/experiences-upgrading-axapta-30-to.html' title='Experiences upgrading Axapta 3.0 to Dynamics AX 4.0'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-834168232858812587</id><published>2008-08-03T10:54:00.000-07:00</published><updated>2008-08-04T07:22:39.339-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Configuring Analysis Services 2005 for AX</title><content type='html'>For use &lt;strong&gt;Analysis Services 2005&lt;/strong&gt; with &lt;strong&gt;Dynamics AX&lt;/strong&gt;, we need to ensure that DSO (Decision Support Objects) is well configured.  Take a look to the following post for more information (NOTE: this post refers to Project 2007 but it is applicable to AX): &lt;br&gt;&lt;br&gt;

&lt;a href="http://www.pptspaces.com/msprojectreporterblog/Lists/Posts/Post.aspx?ID=25"&gt;http://www.pptspaces.com/msprojectreporterblog/Lists/Posts/Post.aspx?ID=25&lt;/a&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Important steps:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

1. Ensure you have installed the following components:&lt;br&gt;
&amp;nbsp;&amp;nbsp;- Microsoft SQL Server Native Client&lt;br&gt;
&amp;nbsp;&amp;nbsp;- Microsoft SQL Server 2005 Management Objects Collection&lt;br&gt;
&amp;nbsp;&amp;nbsp;- Microsoft SQL Server 2005 Backward Compatibility Components&lt;br&gt;&lt;br&gt;

2. Create the old style shared folder (MSOLAPRepository$), normally in &lt;em&gt;C:\Program Files\Microsoft SQL Server\MSSQL.2\OLAP\&lt;strong&gt;DSO9&lt;/strong&gt;&lt;/em&gt; for example.&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;- Share this folder as &lt;strong&gt;MSOLAPRepository$&lt;/strong&gt;. &lt;br&gt;
&amp;nbsp;&amp;nbsp;- Se permissions for &lt;em&gt;EveryOne&lt;/em&gt; or any &lt;em&gt;OLAP users group&lt;/em&gt; as &lt;em&gt;Change&lt;/em&gt; (they need permissions to modify folder's content).&lt;br&gt;
&amp;nbsp;&amp;nbsp;- Set &lt;em&gt;Full control&lt;/em&gt; to &lt;strong&gt;SQLServer2005MSOLAPUser$SERVERNAME$MSSQLSERVER&lt;/strong&gt;.  This user can be located in the &lt;em&gt;ServerName&lt;/em&gt; instance.&lt;br&gt;&lt;br&gt;

3. Copy &lt;strong&gt;msmdrep.mdb&lt;/strong&gt; to this location (DSO9).  You can get a copy of this file from &lt;a href="http://www.pptspaces.com/msprojectreporterblog/Shared%20Files/msmdrep.zip"&gt;http://www.pptspaces.com/msprojectreporterblog/Shared%20Files/msmdrep.zip&lt;/a&gt;&lt;br&gt;&lt;br&gt;

4. Configure data access connection and locks folders: (Open the &lt;em&gt;Analysis Services's  properties&lt;/em&gt; dialog using the &lt;em&gt;SQL Server Mananagement studio&lt;/em&gt; and selection the option &lt;em&gt;"Show Advance (All) properties"&lt;/em&gt;)&lt;br&gt;&lt;br&gt;  

&amp;nbsp;&amp;nbsp;- Configure the &lt;strong&gt;DSO\LocksDirectory&lt;/strong&gt; property with the correct path, ex. &lt;em&gt;C:\Program Files\Microsoft SQL Server\MSSQL.2\OLAP\DSO9&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;- Configure the &lt;strong&gt;DSO\ RemoteLocksDirectory&lt;/strong&gt; property as &lt;strong&gt;\\ServerName\MSOLAPRepository$\&lt;/strong&gt;. &lt;em&gt;Here is the tip different from the original post.&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;- Configure the &lt;strong&gt;DSO\ RemoteRepositoryConnectionString&lt;/strong&gt; selecting the 
&lt;strong&gt;Microsoft Jet 4.0 OLE DB Provider &lt;/strong&gt; but setting the path as &lt;strong&gt;\\ServerName\MSOLAPRepository$\msmdrep.mdb&lt;/strong&gt;.  &lt;em&gt;Here is another difference from the original post.&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&amp;nbsp;&amp;nbsp;- Configure the &lt;strong&gt;DSO\ RepositoryConnectionString&lt;/strong&gt; property but in this case, use the full local path for the msmdrep.mdb file, ex. &lt;em&gt;C:\Program Files\Microsoft SQL Server\MSSQL.2\OLAP\DSO9\msmdrep.mdb&lt;/em&gt;&lt;br&gt;&lt;br&gt;

Thats all, try it, transfer and process some cubes.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; Remember define use'r permissions (for cubes) and administrator's permissions (for server/system).&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-834168232858812587?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/834168232858812587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=834168232858812587' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/834168232858812587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/834168232858812587'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/configuring-analysis-services-2005-for.html' title='Configuring Analysis Services 2005 for AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-7984603875853329678</id><published>2008-08-03T07:55:00.000-07:00</published><updated>2008-08-03T09:57:36.892-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>AX Database Performance</title><content type='html'>Here is an excellent post about AX database performance applying a checking list:&lt;br&gt;&lt;br&gt;

&lt;a href="http://blogs.msdn.com/axperf/archive/2008/03/10/welcome-database-configuration-checklist-part-1.aspx"&gt;http://blogs.msdn.com/axperf/archive/2008/03/10/welcome-database-configuration-checklist-part-1.aspx&lt;/a&gt;&lt;br&gt;&lt;br&gt;

Some tips:&lt;br&gt;&lt;br&gt;

- Max Degree of Parallelism (MAXDOP instance-wide)&lt;br&gt;
   &amp;nbsp;&amp;nbsp;- OLTP (normal operations0: Set Max Degree of Parallelism to 1)&lt;br&gt;
   &amp;nbsp;&amp;nbsp;- Upgrade: set to # of physical processor cores, ...&lt;br&gt;
- Activate AWE only for 32-bits systems&lt;br&gt;
- Separate log and data files&lt;br&gt;
- Configure several temp DBs&lt;br&gt;
- Set Read-Committed Snapshot Isolation = true&lt;br&gt;&lt;br&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;ALTER&lt;/span&gt; &lt;span class="kwrd"&gt;DATABASE&lt;/span&gt; &amp;lt;ax &lt;span class="kwrd"&gt;database&lt;/span&gt; name&amp;gt;

    &lt;span class="kwrd"&gt;SET&lt;/span&gt; READ_COMMITTED_SNAPSHOT &lt;span class="kwrd"&gt;ON&lt;/span&gt;;
&lt;/pre&gt;&lt;br&gt;
- Physical storage configuration (RAID, separate logs and data files, etc.)&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-7984603875853329678?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/7984603875853329678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=7984603875853329678' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7984603875853329678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7984603875853329678'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/08/ax-database-performance.html' title='AX Database Performance'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8701947207794128630</id><published>2008-07-25T15:42:00.000-07:00</published><updated>2008-07-25T15:50:16.318-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><title type='text'>AX user cannot make login</title><content type='html'>Sometimes, an user cannot make login with AX 4.0.  It happen if user was moved or any change in the Active Directory was performed.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Solution:&lt;/strong&gt; disable the user, save the record.  Then, re-enable the user and save again.&lt;br&gt;&lt;br&gt;

AX refresh the user's SID executing this action.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8701947207794128630?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8701947207794128630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8701947207794128630' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8701947207794128630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8701947207794128630'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/07/ax-user-cannot-make-login.html' title='AX user cannot make login'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6397965533678608216</id><published>2008-06-18T13:06:00.001-07:00</published><updated>2008-06-18T13:24:48.025-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>How to enable or disable joined dataSources</title><content type='html'>Here the problem: I need a method to enable or disable an exist join link between two datasources, so, I found two practical solutions:&lt;br&gt;&lt;br&gt;

&lt;strong&gt;1. Using only X++ code:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

- The init method (in this sample, I'm using the vendTrans datasource):

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; init()
{
    super();

    ...

    &lt;span class="rem"&gt;// Here starts my code&lt;/span&gt;
    myDS = &lt;span class="kwrd"&gt;this&lt;/span&gt;.query().dataSourceTable(tableNum(VendTrans)).addDataSource(tableNum(myTable));
    myDS.joinMode(JoinMode::ExistsJoin);
    myDS.addLink(fieldNum(VendTrans, DocumentNum), fieldNum(myTable, DocumentNum));
    myQueryRange = myDS.addRange(fieldnum(myTable, anyField));
    myDS.enabled(&lt;span class="kwrd"&gt;false&lt;/span&gt;);  &lt;span class="rem"&gt;// Disabled until we need it&lt;/span&gt;
    &lt;span class="rem"&gt;// End&lt;/span&gt;
}
&lt;/pre&gt;

- Then, in anywhere:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; ((myFilterValue == &lt;span class="str"&gt;""&lt;/span&gt;) || (myFilterValue == &lt;span class="str"&gt;"*"&lt;/span&gt;))
    {
        myDS.enabled(&lt;span class="kwrd"&gt;false&lt;/span&gt;);  &lt;span class="rem"&gt;// Disable the DS, then none filter is applied&lt;/span&gt;
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
    {
        ...

        myQueryRange.&lt;span class="kwrd"&gt;value&lt;/span&gt;(myFilterValue);
        myDS.enabled(&lt;span class="kwrd"&gt;true&lt;/span&gt;);  &lt;span class="rem"&gt;// Enable DS, then any filter is applied with the existing join link&lt;/span&gt;
    }
    
    VendTrans_ds.executeQuery();
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;2. Using DataSources in design mode:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

- If the DataSource was added in design mode, we need to change the previous code as this:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; ((myFilterValue == &lt;span class="str"&gt;""&lt;/span&gt;) || (myFilterValue == &lt;span class="str"&gt;"*"&lt;/span&gt;))
    {
        myTable_ds.query().dataSourceTable(tablenum(myTable)).enabled(&lt;span class="kwrd"&gt;false&lt;/span&gt;);  &lt;span class="rem"&gt;// Disable the DS, then none filter is applied&lt;/span&gt;
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
    {
        ...

        myQueryRange.&lt;span class="kwrd"&gt;value&lt;/span&gt;(myFilterValue);
        myTable_ds.query().dataSourceTable(tablenum(myTable)).enabled(&lt;span class="kwrd"&gt;true&lt;/span&gt;);  &lt;span class="rem"&gt;// Enable DS, then any filter is applied with the existing join link&lt;/span&gt;
    }
    
    VendTrans_ds.executeQuery();
&lt;/pre&gt;&lt;br&gt;&lt;br&gt;

&lt;em&gt;NOTE:&lt;/em&gt; myQuery value must be initialized in the init method from myTable datasource and the relation between tables must be specified (In this sample, myTable.myField = vendTrans.DocumentNum).&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6397965533678608216?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6397965533678608216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6397965533678608216' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6397965533678608216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6397965533678608216'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/06/how-to-enable-or-disable-joined.html' title='How to enable or disable joined dataSources'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5678736447060806585</id><published>2008-06-03T11:45:00.000-07:00</published><updated>2008-06-03T11:50:46.785-07:00</updated><title type='text'>I'm back</title><content type='html'>Hi everyone!&lt;br&gt;&lt;br&gt;

I'm back.  I was moving to Canada with all my family.   &amp;nbsp;Now, here we are, in &lt;strong&gt;Montreal, QC, Canada&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;

&lt;em&gt;Comming soon&lt;/em&gt;: SharePoint, .NET windows applications, Dynamics AX improvements, and more.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5678736447060806585?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5678736447060806585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5678736447060806585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5678736447060806585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5678736447060806585'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/06/im-back.html' title='I&apos;m back'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-3057116705827189005</id><published>2008-03-17T14:46:00.000-07:00</published><updated>2008-03-17T15:10:28.012-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Printing directly to PDF in AX</title><content type='html'>References: &lt;a href="http://www.axaptapedia.com/index.php/Printer_Settings_and_Run_From_Code"&gt;AxaptaPedia&lt;/a&gt;&lt;br&gt;&lt;br&gt;

To achieve this task, we need to set some values to the printing settings before running the report like this:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Variables&lt;/span&gt;
PrintJobSettings    printJobSettings;
ReportRun           myReportRun;

...


&lt;span class="rem"&gt;// Getting the report settings&lt;/span&gt;
printJobSettings = myReportRun.printJobSettings();

&lt;span class="rem"&gt;// Setting our parameters&lt;/span&gt;
printJobSettings.setTarget(PrintMedium::File);
printJobSettings.preferredTarget(PrintMedium::File);

printJobSettings.format(PrintFormat::PDF);
printJobSettings.preferredFileFormat(PrintFormat::PDF);

printJobSettings.fileName(&lt;span class="str"&gt;"c:\\attachment.pdf"&lt;/span&gt;);

&lt;span class="rem"&gt;// Saving values&lt;/span&gt;
myReportRun.unpackPrintJobSettings(printJobSettings.packPrintJobSettings());

&lt;span class="rem"&gt;// Running the report&lt;/span&gt;
myReportRun.run();&lt;/pre&gt;

Before running the report, we can set query's values:

&lt;pre class="csharpcode"&gt;
query = myReportRun.query();
qbds = query.dataSourceNo(1);

qbds.range(1).&lt;span class="kwrd"&gt;value&lt;/span&gt;(_custTable.CustAccount);
qbds.range(2).&lt;span class="kwrd"&gt;value&lt;/span&gt;(&lt;span class="str"&gt;""&lt;/span&gt;);
qbds.range(3).&lt;span class="kwrd"&gt;value&lt;/span&gt;(queryvalue(NoYes::Yes));

myReportRun.run();&lt;/pre&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; For using a PDF Printer like "PDFCreator", simply set the deviceName like this:

&lt;pre class="csharpcode"&gt;
myReportRun.deviceName(&lt;span class="str"&gt;"PDFCreator"&lt;/span&gt;);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3057116705827189005?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3057116705827189005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3057116705827189005' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3057116705827189005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3057116705827189005'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/03/printing-directly-to-pdf.html' title='Printing directly to PDF in AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-715549483120910290</id><published>2008-03-05T08:11:00.000-08:00</published><updated>2008-03-06T08:16:28.678-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Complex Queries in AX</title><content type='html'>Overview from &lt;a href="http://www.axaptapedia.com/Expressions_in_query_ranges"&gt;Axaptapedia - Expressions in query ranges&lt;/a&gt;&lt;br&gt;&lt;br&gt;

For build complex queries, we can use any field, but normally, &lt;strong&gt;DataAreaId&lt;/strong&gt; is used.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
query = &lt;span class="kwrd"&gt;new&lt;/span&gt; Query();
dsInventTable = query.addDataSource(tableNum(InventTable));

&lt;span class="rem"&gt;// Add our range&lt;/span&gt;
queryBuildRange = dsInventTable.addRange(fieldNum(InventTable, DataAreaId));&lt;/pre&gt;

&lt;strong&gt;Query values:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
queryBuildRange.&lt;span class="kwrd"&gt;value&lt;/span&gt;(strFmt(&lt;span class="str"&gt;'((ItemType == %1) || (ItemId == "%2"))'&lt;/span&gt;, 
    any2int(ItemType::Service),
    queryValue(&lt;span class="str"&gt;"B-R14"&lt;/span&gt;)));&lt;/pre&gt;

&lt;strong&gt;Working with dates:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
queryBuildRange.&lt;span class="kwrd"&gt;value&lt;/span&gt;(strFmt(&lt;span class="str"&gt;'(ModifiedDate &amp;gt; %1)'&lt;/span&gt;, Date2StrXpp(01012000)));&lt;/pre&gt;

&lt;strong&gt;Complex queries with relations:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
query = &lt;span class="kwrd"&gt;new&lt;/span&gt; Query();
dsInventTable = query.addDataSource(tableNum(InventTable), tableStr(InventTable));
dsInventItemBarCode = dsInventTable.addDataSource(tableNum(InventItemBarCode), tableStr(InventItemBarCode));
dsInventItemBarCode.relations(&lt;span class="kwrd"&gt;true&lt;/span&gt;);
dsInventItemBarCode.joinMode(JoinMode::ExistsJoin);
 
&lt;span class="rem"&gt;// Add our two ranges&lt;/span&gt;
queryBuildRange1 = dsInventTable.addRange(fieldNum(InventTable, DataAreaId));
queryBuildRange2 = dsInventItemBarCode.addRange(fieldNum(InventItemBarCode, DataAreaId));

queryBuildRange2.value(strFmt('(ModifiedDate &gt; InventTable.ModifiedDate)'));
&lt;/pre&gt;

Or 

&lt;pre class="csharpcode"&gt;
queryBuildRange2.&lt;span class="kwrd"&gt;value&lt;/span&gt;(strFmt(&lt;span class="str"&gt;'((%1.%2 == %3) || ((%1.%2 == %4) &amp;amp;&amp;amp; (%1.%5 == %6)))'&lt;/span&gt;,
    query.dataSourceTable(tableNum(InventTable)).name(), &lt;span class="rem"&gt;// InventTable %1&lt;/span&gt;
    fieldStr(InventTable, ItemType), &lt;span class="rem"&gt;// ItemType %2&lt;/span&gt;
    any2int(ItemType::Service), &lt;span class="rem"&gt;// %3&lt;/span&gt;
    any2int(ItemType::Item), &lt;span class="rem"&gt;// %4&lt;/span&gt;
    fieldStr(InventTable, ItemId), &lt;span class="rem"&gt;// ItemId %5&lt;/span&gt;
    fieldStr(InventItemBarCode, ItemId))); // %6 &lt;/pre&gt;

&lt;strong&gt;Dimensions:&lt;/strong&gt;  &lt;em&gt;Corrected.  Thanks Alex.&lt;/em&gt;&lt;br&gt;&lt;br&gt;  

&lt;pre class="csharpcode"&gt;
queryBuildRange = dsLedgerTrans.addRange(fieldId2Ext(fieldNum(LedgerTrans, Dimension),1)); 

queryBuildRange.&lt;span class="kwrd"&gt;value&lt;/span&gt;(&lt;span class="str"&gt;"some value"&lt;/span&gt;);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-715549483120910290?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/715549483120910290/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=715549483120910290' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/715549483120910290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/715549483120910290'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/03/queries-in-ax.html' title='Complex Queries in AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8482781704593086709</id><published>2008-03-01T07:12:00.000-08:00</published><updated>2008-03-01T07:18:30.521-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>Displaying the traditional Main Menu in AX</title><content type='html'>If you don't like the new &lt;strong&gt;Navigation Pane&lt;/strong&gt; from Dynamics AX, you can turn on the traditional &lt;em&gt;Main Menu&lt;/em&gt; dialog by changing the &lt;em&gt;SysUserSetup&lt;/em&gt; form that allows you to specify the &lt;em&gt;Startup Menu item&lt;/em&gt;.

Open the &lt;em&gt;SysUserSetup&lt;/em&gt; form from the AOT, go to method &lt;em&gt;buildStartupMenuCombo&lt;/em&gt;, line 56, and change it as:

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;//if( ! mainMenuItems.in(object.treeNodeName()) )&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; ((!mainMenuItems.&lt;span class="kwrd"&gt;in&lt;/span&gt;(&lt;span class="kwrd"&gt;object&lt;/span&gt;.treeNodeName())) || (&lt;span class="kwrd"&gt;object&lt;/span&gt;.AOTname() == &lt;span class="str"&gt;"MainMenu"&lt;/span&gt;))
&lt;/pre&gt;

Now, you can open the &lt;em&gt;Options&lt;/em&gt; dialog and set the &lt;em&gt;Main Menu&lt;/em&gt; as the &lt;em&gt;Startup Menu item&lt;/em&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8482781704593086709?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8482781704593086709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8482781704593086709' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8482781704593086709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8482781704593086709'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/03/displaying-traditional-main-menu-in-ax.html' title='Displaying the traditional Main Menu in AX'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-9031001677406528927</id><published>2008-02-09T08:51:00.000-08:00</published><updated>2008-02-09T09:11:30.988-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Sending mail using SmtpClient</title><content type='html'>Self explained sample:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Mail message construction&lt;/span&gt;
MailMessage mm = &lt;span class="kwrd"&gt;new&lt;/span&gt; MailMessage(&lt;span class="str"&gt;"youraccount@gmail.com"&lt;/span&gt;, &lt;span class="str"&gt;"destination@mail.com"&lt;/span&gt;);

&lt;span class="rem"&gt;// content&lt;/span&gt;
mm.Subject = &lt;span class="str"&gt;"testing message"&lt;/span&gt;;
mm.Body = &lt;span class="str"&gt;"hello... from .net c# mailmessage"&lt;/span&gt;;
mm.CC.Add(&lt;span class="str"&gt;"copycc@mail.com"&lt;/span&gt;);
mm.CC.Add(&lt;span class="str"&gt;"copycc2@mail.com"&lt;/span&gt;);
mm.Bcc.Add(&lt;span class="str"&gt;"copybcc@mail.com"&lt;/span&gt;);

&lt;span class="rem"&gt;// some attachments&lt;/span&gt;
mm.Attachments.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Attachment(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;));

&lt;span class="rem"&gt;// Sending message&lt;/span&gt;
SmtpClient sc = &lt;span class="kwrd"&gt;new&lt;/span&gt; SmtpClient(&lt;span class="str"&gt;"smtp.gmail.com"&lt;/span&gt;, 587);

&lt;span class="rem"&gt;// our account credentials&lt;/span&gt;
sc.Credentials = &lt;span class="kwrd"&gt;new&lt;/span&gt; NetworkCredential(&lt;span class="str"&gt;"youraccount@gmail.com"&lt;/span&gt;, &lt;span class="str"&gt;"yourpassword"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);
sc.EnableSsl = &lt;span class="kwrd"&gt;true&lt;/span&gt;;

&lt;span class="rem"&gt;// Catching result&lt;/span&gt;
&lt;span class="kwrd"&gt;try&lt;/span&gt;
{
    sc.Send(mm);
    MessageBox.Show(&lt;span class="str"&gt;"Message sent"&lt;/span&gt;);
}
&lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
{
    MessageBox.Show(&lt;span class="str"&gt;"Error: "&lt;/span&gt; + ex.Message);
}
&lt;/pre&gt;

For send HTML content and pictures, we need to use &lt;em&gt;Alternated views&lt;/em&gt; with &lt;em&gt;LinkedResource&lt;/em&gt; instead of the &lt;em&gt;Body&lt;/em&gt; property.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Mail message construction&lt;/span&gt;
MailMessage mm = &lt;span class="kwrd"&gt;new&lt;/span&gt; MailMessage(&lt;span class="str"&gt;"youraccount@gmail.com"&lt;/span&gt;, &lt;span class="str"&gt;"destination@mail.com"&lt;/span&gt;);

&lt;span class="rem"&gt;// content&lt;/span&gt;
mm.Subject = &lt;span class="str"&gt;"testing message"&lt;/span&gt;;

&lt;span class="rem"&gt;//mm.Body = "hello... from .net c# mailmessage"; // deprecated, now we're using alternate views&lt;/span&gt;

mm.CC.Add(&lt;span class="str"&gt;"copycc@mail.com"&lt;/span&gt;);
mm.CC.Add(&lt;span class="str"&gt;"copycc2@mail.com"&lt;/span&gt;);
mm.Bcc.Add(&lt;span class="str"&gt;"copybcc@mail.com"&lt;/span&gt;);

&lt;span class="rem"&gt;// some attachments&lt;/span&gt;
mm.Attachments.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Attachment(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;));

&lt;span class="rem"&gt;// An HTML message body including one image&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; htmlBody = &lt;span class="str"&gt;"&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;hello... from .net c# mailmessage&amp;lt;br&amp;gt;&amp;lt;img src=\"cid:MyPicture\"&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;"&lt;/span&gt;;

AlternateView avHtml = AlternateView.CreateAlternateViewFromString(htmlBody, &lt;span class="kwrd"&gt;null&lt;/span&gt;, MediaTypeNames.Text.Html);

&lt;span class="rem"&gt;// Now, linking our image as an embedded resource&lt;/span&gt;
LinkedResource MyPicture = &lt;span class="kwrd"&gt;new&lt;/span&gt; LinkedResource(&lt;span class="str"&gt;"c:\\MyPicture.jpg"&lt;/span&gt;, MediaTypeNames.Image.Jpeg);
MyPicture.ContentId = &lt;span class="str"&gt;"MyPicture"&lt;/span&gt;;

avHtml.LinkedResources.Add(MyPicture); &lt;span class="rem"&gt;// Linking the image&lt;/span&gt;

&lt;span class="rem"&gt;// For clients that do not support HTML content&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; textBody = &lt;span class="str"&gt;"hello... from .net c# mailmessage... You're missing my picture."&lt;/span&gt;;

AlternateView avText = AlternateView.CreateAlternateViewFromString(textBody, &lt;span class="kwrd"&gt;null&lt;/span&gt;, MediaTypeNames.Text.Plain);

&lt;span class="rem"&gt;// Add the alternate views&lt;/span&gt;
mm.AlternateViews.Add(avHtml);
mm.AlternateViews.Add(avText);


&lt;span class="rem"&gt;// Sending message&lt;/span&gt;
SmtpClient sc = &lt;span class="kwrd"&gt;new&lt;/span&gt; SmtpClient(&lt;span class="str"&gt;"smtp.gmail.com"&lt;/span&gt;, 587);

&lt;span class="rem"&gt;// our account credentials&lt;/span&gt;
sc.Credentials = &lt;span class="kwrd"&gt;new&lt;/span&gt; NetworkCredential(&lt;span class="str"&gt;"youraccount@gmail.com"&lt;/span&gt;, &lt;span class="str"&gt;"yourpassword"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);
sc.EnableSsl = &lt;span class="kwrd"&gt;true&lt;/span&gt;;

&lt;span class="rem"&gt;// Catching result&lt;/span&gt;
&lt;span class="kwrd"&gt;try&lt;/span&gt;
{
    sc.Send(mm);
    MessageBox.Show(&lt;span class="str"&gt;"Message sent"&lt;/span&gt;);
}
&lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
{
    MessageBox.Show(&lt;span class="str"&gt;"Error: "&lt;/span&gt; + ex.Message);
}
&lt;/pre&gt;

For asynchronous operations:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Mail message construction&lt;/span&gt;
MailMessage mm = &lt;span class="kwrd"&gt;new&lt;/span&gt; MailMessage(&lt;span class="str"&gt;"youraccount@gmail.com"&lt;/span&gt;, &lt;span class="str"&gt;"destination@mail.com"&lt;/span&gt;);

&lt;span class="rem"&gt;// content&lt;/span&gt;
mm.Subject = &lt;span class="str"&gt;"testing message"&lt;/span&gt;;
mm.Body = &lt;span class="str"&gt;"hello... from .net c# mailmessage"&lt;/span&gt;;
mm.CC.Add(&lt;span class="str"&gt;"copycc@mail.com"&lt;/span&gt;);
mm.CC.Add(&lt;span class="str"&gt;"copycc2@mail.com"&lt;/span&gt;);
mm.Bcc.Add(&lt;span class="str"&gt;"copybcc@mail.com"&lt;/span&gt;);

&lt;span class="rem"&gt;// some attachments&lt;/span&gt;
mm.Attachments.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Attachment(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;));

&lt;span class="rem"&gt;// Sending message&lt;/span&gt;
SmtpClient sc = &lt;span class="kwrd"&gt;new&lt;/span&gt; SmtpClient(&lt;span class="str"&gt;"smtp.gmail.com"&lt;/span&gt;, 587);

&lt;span class="rem"&gt;// our account credentials&lt;/span&gt;
sc.Credentials = &lt;span class="kwrd"&gt;new&lt;/span&gt; NetworkCredential(&lt;span class="str"&gt;"youraccount@gmail.com"&lt;/span&gt;, &lt;span class="str"&gt;"yourpassword"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);
sc.EnableSsl = &lt;span class="kwrd"&gt;true&lt;/span&gt;;

&lt;span class="rem"&gt;// Asynchronous sending&lt;/span&gt;
sc.SendCompleted += &lt;span class="kwrd"&gt;new&lt;/span&gt; SendCompletedEventHandler(sc_SendCompleted);

sc.SendAsync(mm, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; sc_SendCompleted(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, AsyncCompletedEventArgs e)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Cancelled)
        MessageBox.Show(&lt;span class="str"&gt;"Message cancelled"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Error != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
        MessageBox.Show(&lt;span class="str"&gt;"Error: "&lt;/span&gt; + e.Error.ToString());
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        MessageBox.Show(&lt;span class="str"&gt;"Message sent"&lt;/span&gt;);
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-9031001677406528927?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/9031001677406528927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=9031001677406528927' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/9031001677406528927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/9031001677406528927'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/02/sending-mail-using-smtpclient.html' title='Sending mail using SmtpClient'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-7280617277235311381</id><published>2008-02-08T18:28:00.000-08:00</published><updated>2008-02-09T06:22:09.181-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Creating Code at Runtime (Part 3)</title><content type='html'>See &lt;a href="http://olondono.blogspot.com/2008/02/creating-code-at-runtime.html"&gt;Creating Code At Runtime - Part 1&lt;/a&gt;&lt;br&gt;
See &lt;a href="http://olondono.blogspot.com/2008/02/creating-code-at-runtime-part-2.html"&gt;Creating Code At Runtime - Part 2&lt;/a&gt;&lt;br&gt;&lt;br&gt;

I want to change our previous delegate for one more standard, like &lt;em&gt;EventHandler&lt;/em&gt;.  The new class must looks like:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;delegate&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BeforeBuildFullNameHandler(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e);

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _firstname;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _lastname;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; BeforeBuildFullNameHandler BeforeBuildFullName;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _firstname; }
        set { _firstname = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _lastname; }
        set { _lastname = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
        _firstname = &lt;span class="str"&gt;""&lt;/span&gt;;
        _lastname = &lt;span class="str"&gt;""&lt;/span&gt;;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person(&lt;span class="kwrd"&gt;string&lt;/span&gt; firstname, &lt;span class="kwrd"&gt;string&lt;/span&gt; lastname)
    {
        FirstName = firstname;
        LastName = lastname;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFullName()
    {
        DispatchBeforeBuildFullName();

        &lt;span class="kwrd"&gt;return&lt;/span&gt; FirstName + &lt;span class="str"&gt;" "&lt;/span&gt; + LastName;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DispatchBeforeBuildFullName()
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (BeforeBuildFullName != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            BeforeBuildFullName(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; EventArgs());
    }
}
&lt;/pre&gt;

&lt;strong&gt;Steps:&lt;/strong&gt;

1. We need to change the Invoke, BeginInvoke and EndInvoke methods:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Now, we need to implement three methods:&lt;/span&gt;
&lt;span class="rem"&gt;// Invoke, BeginInvoke and EndInvoke&lt;/span&gt;
MethodBuilder methodBuilder;

&lt;span class="rem"&gt;// Because we are using a delegate with parameters,&lt;/span&gt;
&lt;span class="rem"&gt;// then, we need to declare four parameters for &lt;/span&gt;
&lt;span class="rem"&gt;// asynchronous operations: AsyncCallback and object (any)&lt;/span&gt;
Type[] beginParameters = &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[4];

beginParameters[0] = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;object&lt;/span&gt;);
beginParameters[1] = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(EventArgs);
beginParameters[2] = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(AsyncCallback);
beginParameters[3] = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;object&lt;/span&gt;);

&lt;span class="rem"&gt;// BeginInvoke for Asynchronous call&lt;/span&gt;
methodBuilder = delegateBuilder.DefineMethod(&lt;span class="str"&gt;"BeginInvoke"&lt;/span&gt;, maDelegate, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IAsyncResult), beginParameters);
methodBuilder.SetImplementationFlags(mia);

&lt;span class="rem"&gt;// EndInvoke for Asynchronous call&lt;/span&gt;
methodBuilder = delegateBuilder.DefineMethod(&lt;span class="str"&gt;"EndInvoke"&lt;/span&gt;, maDelegate, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;void&lt;/span&gt;), &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IAsyncResult) });
methodBuilder.SetImplementationFlags(mia);

&lt;span class="rem"&gt;// Invoke for Synchronous call&lt;/span&gt;
methodBuilder = delegateBuilder.DefineMethod(&lt;span class="str"&gt;"Invoke"&lt;/span&gt;, maDelegate, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;void&lt;/span&gt;), &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;object&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(EventArgs) });
methodBuilder.DefineParameter(1, ParameterAttributes.In, &lt;span class="str"&gt;"sender"&lt;/span&gt;);
methodBuilder.DefineParameter(2, ParameterAttributes.In, &lt;span class="str"&gt;"e"&lt;/span&gt;);
methodBuilder.SetImplementationFlags(mia);
&lt;/pre&gt;

2. Also, we need to change the &lt;em&gt;Dispath&lt;/em&gt; method:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// And here, the code for the dispatchMethod&lt;/span&gt;
ilgen = dispatchMethodBuilder.GetILGenerator();

LocalBuilder local = ilgen.DeclareLocal(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;bool&lt;/span&gt;));
System.Reflection.Emit.Label label = ilgen.DefineLabel();

ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, eventFieldBuilder);    &lt;span class="rem"&gt;// Asking for the event field&lt;/span&gt;
ilgen.Emit(OpCodes.Ldnull);                        &lt;span class="rem"&gt;// is null ?&lt;/span&gt;
ilgen.Emit(OpCodes.Ceq);
ilgen.Emit(OpCodes.Stloc_0);
ilgen.Emit(OpCodes.Ldloc_0);
ilgen.Emit(OpCodes.Brtrue_S, label);            &lt;span class="rem"&gt;// if null, return&lt;/span&gt;

ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, eventFieldBuilder);    &lt;span class="rem"&gt;// call the event&lt;/span&gt;

ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Newobj, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(EventArgs).GetConstructor(Type.EmptyTypes)); &lt;span class="rem"&gt;// Now, we include a new empty EventArgs object&lt;/span&gt;

ilgen.Emit(OpCodes.Callvirt, delegateType.GetMethod(&lt;span class="str"&gt;"Invoke"&lt;/span&gt;));

ilgen.Emit(OpCodes.Nop);
ilgen.MarkLabel(label);
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-7280617277235311381?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/7280617277235311381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=7280617277235311381' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7280617277235311381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7280617277235311381'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/02/creating-code-at-runtime-part-3.html' title='Creating Code at Runtime (Part 3)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-1455533457753741243</id><published>2008-02-08T17:46:00.000-08:00</published><updated>2008-02-08T18:36:15.298-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Creating Code at Runtime (Part 2)</title><content type='html'>See &lt;a href="http://olondono.blogspot.com/2008/02/creating-code-at-runtime.html"&gt;Creating Code At Runtime - Part 1&lt;/a&gt;&lt;br&gt;
See &lt;a href="http://olondono.blogspot.com/2008/02/creating-code-at-runtime-part-3.html"&gt;Creating Code At Runtime - Part 3&lt;/a&gt;&lt;br&gt;&lt;br&gt;

If we need to handle events and delegates, as the following sample:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;delegate&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BeforeBuildFullNameHandler();

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _firstname;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _lastname;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; BeforeBuildFullNameHandler BeforeBuildFullName;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _firstname; }
        set { _firstname = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _lastname; }
        set { _lastname = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
        _firstname = &lt;span class="str"&gt;""&lt;/span&gt;;
        _lastname = &lt;span class="str"&gt;""&lt;/span&gt;;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person(&lt;span class="kwrd"&gt;string&lt;/span&gt; firstname, &lt;span class="kwrd"&gt;string&lt;/span&gt; lastname)
    {
        FirstName = firstname;
        LastName = lastname;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFullName()
    {
        DispatchBeforeBuildFullName();

        &lt;span class="kwrd"&gt;return&lt;/span&gt; FirstName + &lt;span class="str"&gt;" "&lt;/span&gt; + LastName;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DispatchBeforeBuildFullName()
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (BeforeBuildFullName != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            BeforeBuildFullName();
    }
}
&lt;/pre&gt;

&lt;strong&gt;Steps:&lt;/strong&gt;

1. Define our dispatching method early, before the &lt;em&gt;GetFullName&lt;/em&gt; method.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Early definition of this method because we use it in GetFullName.&lt;/span&gt;
MethodBuilder dispatchMethodBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"DispatchBeforeBuildFullName"&lt;/span&gt;, MethodAttributes.Private, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;void&lt;/span&gt;), Type.EmptyTypes);
&lt;/pre&gt;

2. Change the &lt;em&gt;GetFullName&lt;/em&gt; method:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Now, a custom method named GetFullName that concatenates FirstName and LastName properties&lt;/span&gt;
MethodBuilder mGetFullNameBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"GetFullName"&lt;/span&gt;, MethodAttributes.Public, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), Type.EmptyTypes);

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = mGetFullNameBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);

ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Call, dispatchMethodBuilder); &lt;span class="rem"&gt;// Now, we include the call to the Dispatch method&lt;/span&gt;
ilgen.Emit(OpCodes.Nop);

ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, mGetFirstNameBuilder); &lt;span class="rem"&gt;// getting the firstname&lt;/span&gt;
ilgen.Emit(OpCodes.Ldstr, &lt;span class="str"&gt;" "&lt;/span&gt;); &lt;span class="rem"&gt;// an space&lt;/span&gt;
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, mGetLastNameBuilder); &lt;span class="rem"&gt;// getting the lastname&lt;/span&gt;

&lt;span class="rem"&gt;// We need the 'Concat' method from string type&lt;/span&gt;
MethodInfo concatMethod = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(String).GetMethod(&lt;span class="str"&gt;"Concat"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;) });

ilgen.Emit(OpCodes.Call, concatMethod); &lt;span class="rem"&gt;// calling concat and returning the result&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

3. The &lt;em&gt;delegate&lt;/em&gt; declaration

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Building a delegate and it's constructor&lt;/span&gt;
TypeBuilder delegateBuilder = modBuilder.DefineType(&lt;span class="str"&gt;"PeopleLibrary.BeforeBuildFullNameHandler"&lt;/span&gt;, TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.Sealed, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(MulticastDelegate));

ConstructorBuilder delegateCtorBuilder = delegateBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;object&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IntPtr) });
delegateCtorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
&lt;/pre&gt;

4.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Method attributes flags&lt;/span&gt;
MethodAttributes maDelegate = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual;
MethodImplAttributes mia = MethodImplAttributes.Runtime | MethodImplAttributes.Managed;
&lt;/pre&gt;

5.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Now, we need to implement three methods:&lt;/span&gt;
&lt;span class="rem"&gt;// Invoke, BeginInvoke and EndInvoke&lt;/span&gt;
MethodBuilder methodBuilder;

&lt;span class="rem"&gt;// Because we are using a delegate without parameters,&lt;/span&gt;
&lt;span class="rem"&gt;// then, we need to declare only two parameters for &lt;/span&gt;
&lt;span class="rem"&gt;// asynchronous operations: AsyncCallback and object (any)&lt;/span&gt;
Type[] beginParameters = &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[2];
beginParameters[0] = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(AsyncCallback);
beginParameters[1] = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;object&lt;/span&gt;);

&lt;span class="rem"&gt;// BeginInvoke for Asynchronous call&lt;/span&gt;
methodBuilder = delegateBuilder.DefineMethod(&lt;span class="str"&gt;"BeginInvoke"&lt;/span&gt;, maDelegate, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IAsyncResult), beginParameters);
methodBuilder.SetImplementationFlags(mia);

&lt;span class="rem"&gt;// EndInvoke for Asynchronous call&lt;/span&gt;
methodBuilder = delegateBuilder.DefineMethod(&lt;span class="str"&gt;"EndInvoke"&lt;/span&gt;, maDelegate, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;void&lt;/span&gt;), &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IAsyncResult) });
methodBuilder.SetImplementationFlags(mia);

&lt;span class="rem"&gt;// Invoke for Synchronous call&lt;/span&gt;
methodBuilder = delegateBuilder.DefineMethod(&lt;span class="str"&gt;"Invoke"&lt;/span&gt;, maDelegate, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;void&lt;/span&gt;), Type.EmptyTypes);
methodBuilder.SetImplementationFlags(mia);&lt;/pre&gt;

6.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Now, we can create this delegate&lt;/span&gt;
Type delegateType = delegateBuilder.CreateType();
&lt;/pre&gt;

7.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Event declaration.  &lt;/span&gt;
&lt;span class="rem"&gt;// The internal event container and the event handler&lt;/span&gt;
FieldBuilder eventFieldBuilder = personBuilder.DefineField(&lt;span class="str"&gt;"BeforeBuildFullName"&lt;/span&gt;, delegateType, FieldAttributes.FamORAssem);
EventBuilder _eventBuilder = personBuilder.DefineEvent(&lt;span class="str"&gt;"BeforeBuildFullName"&lt;/span&gt;, EventAttributes.None, delegateType);
&lt;/pre&gt;

8.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Event methods attributes&lt;/span&gt;
MethodAttributes eventMethodAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
MethodImplAttributes eventMethodImpAtr = MethodImplAttributes.Managed | MethodImplAttributes.Synchronized;
&lt;/pre&gt;

9.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// We need to implement the add_EVENTNAME&lt;/span&gt;
MethodBuilder addMethodBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"add_BeforeBuildFullName"&lt;/span&gt;, eventMethodAttr, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { delegateType });
addMethodBuilder.SetImplementationFlags(eventMethodImpAtr);

&lt;span class="rem"&gt;// We need the 'Combine' method from the Delegate type&lt;/span&gt;
MethodInfo combineInfo = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Delegate).GetMethod(&lt;span class="str"&gt;"Combine"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Delegate), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Delegate) });

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = addMethodBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, eventFieldBuilder);    &lt;span class="rem"&gt;// the event container&lt;/span&gt;
ilgen.Emit(OpCodes.Ldarg_1);                    &lt;span class="rem"&gt;// the new event parameter (argument 1)&lt;/span&gt;
ilgen.Emit(OpCodes.Call, combineInfo);            &lt;span class="rem"&gt;// the Combine method call&lt;/span&gt;
ilgen.Emit(OpCodes.Castclass, delegateType);    &lt;span class="rem"&gt;// casting the return value &lt;/span&gt;
ilgen.Emit(OpCodes.Stfld, eventFieldBuilder);  &lt;span class="rem"&gt;// saving into the event container&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

10.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// We need to implement the remove_EVENTNAME&lt;/span&gt;
MethodBuilder removeMethodBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"remove_BeforeBuildFullName"&lt;/span&gt;, eventMethodAttr, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { delegateType });
removeMethodBuilder.SetImplementationFlags(eventMethodImpAtr);

&lt;span class="rem"&gt;// We need the 'Remove' method from the Delegate type&lt;/span&gt;
MethodInfo removeInfo = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Delegate).GetMethod(&lt;span class="str"&gt;"Remove"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Delegate), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Delegate) });

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = removeMethodBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, eventFieldBuilder);    &lt;span class="rem"&gt;// the event container&lt;/span&gt;
ilgen.Emit(OpCodes.Ldarg_1);                    &lt;span class="rem"&gt;// the event parameter (argument 1) for removing&lt;/span&gt;
ilgen.Emit(OpCodes.Call, removeInfo);            &lt;span class="rem"&gt;// the Remove method call&lt;/span&gt;
ilgen.Emit(OpCodes.Castclass, delegateType);   &lt;span class="rem"&gt;// casting the return value &lt;/span&gt;
ilgen.Emit(OpCodes.Stfld, eventFieldBuilder);  &lt;span class="rem"&gt;// saving into the event container&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

11.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Finally, setting the AddOn and RemoveOn methods for our event&lt;/span&gt;
_eventBuilder.SetAddOnMethod(addMethodBuilder);
_eventBuilder.SetRemoveOnMethod(removeMethodBuilder);
&lt;/pre&gt;

12.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// And here, the code for the dispatchMethod&lt;/span&gt;
ilgen = dispatchMethodBuilder.GetILGenerator();

LocalBuilder local = ilgen.DeclareLocal(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;bool&lt;/span&gt;));
System.Reflection.Emit.Label label = ilgen.DefineLabel();

ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, eventFieldBuilder);    &lt;span class="rem"&gt;// Asking for the event field&lt;/span&gt;
ilgen.Emit(OpCodes.Ldnull);                    &lt;span class="rem"&gt;// is null ?&lt;/span&gt;
ilgen.Emit(OpCodes.Ceq);
ilgen.Emit(OpCodes.Stloc_0);
ilgen.Emit(OpCodes.Ldloc_0);
ilgen.Emit(OpCodes.Brtrue_S, label);            &lt;span class="rem"&gt;// if null, return&lt;/span&gt;

ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, eventFieldBuilder);    &lt;span class="rem"&gt;// call the event&lt;/span&gt;
ilgen.Emit(OpCodes.Callvirt, delegateType.GetMethod(&lt;span class="str"&gt;"Invoke"&lt;/span&gt;));
ilgen.Emit(OpCodes.Nop);
ilgen.MarkLabel(label);
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

13.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Finally, create the type and save the assembly&lt;/span&gt;
personBuilder.CreateType();

asmBuilder.Save(&lt;span class="str"&gt;"PeopleLibrary.dll"&lt;/span&gt;);
&lt;/pre&gt;

14. Using the library:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    Person p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"oscar"&lt;/span&gt;, &lt;span class="str"&gt;"londono"&lt;/span&gt;);

    p.BeforeBuildFullName += &lt;span class="kwrd"&gt;new&lt;/span&gt; BeforeBuildFullNameHandler(p_BeforeBuildFullName);

    MessageBox.Show(p.GetFullName());
}

&lt;span class="kwrd"&gt;void&lt;/span&gt; p_BeforeBuildFullName()
{
    MessageBox.Show(&lt;span class="str"&gt;"Before build full name"&lt;/span&gt;);
}
&lt;/pre&gt;


&lt;strong&gt;References:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;a href="http://bltoolkit.net/Source/Aspects/AsyncAspectBuilder.cs.htm"&gt;Business Logic Toolkit for .NET&lt;/a&gt;
&lt;br&gt;
&lt;a href="http://www.rainsts.net/article.asp?id=393"&gt;Emit: 9. Event by yuhen&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-1455533457753741243?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/1455533457753741243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=1455533457753741243' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1455533457753741243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1455533457753741243'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/02/creating-code-at-runtime-part-2.html' title='Creating Code at Runtime (Part 2)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2129490894400507216</id><published>2008-02-08T16:53:00.000-08:00</published><updated>2008-02-08T18:37:04.243-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Creating Code at Runtime / System.Reflection.Emit</title><content type='html'>Here an example how we can create code at runtime.  In this sample, I try to create the following class at runtime:

&lt;pre class="csharpcode"&gt;

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _firstname;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _lastname;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _firstname; }
        set { _firstname = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _lastname; }
        set { _lastname = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
        _firstname = &lt;span class="str"&gt;""&lt;/span&gt;;
        _lastname = &lt;span class="str"&gt;""&lt;/span&gt;;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person(&lt;span class="kwrd"&gt;string&lt;/span&gt; firstname, &lt;span class="kwrd"&gt;string&lt;/span&gt; lastname)
    {
        FirstName = firstname;
        LastName = lastname;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFullName()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; FirstName + &lt;span class="str"&gt;" "&lt;/span&gt; + LastName;
    }
}
&lt;/pre&gt;

First of all, I'm going to implement the class as simple as posible, avoiding delegates an events.  Here the result:

1.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our intermediate language generator&lt;/span&gt;
ILGenerator ilgen;

&lt;span class="rem"&gt;// The assembly builder&lt;/span&gt;
AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(&lt;span class="kwrd"&gt;new&lt;/span&gt; AssemblyName(&lt;span class="str"&gt;"PeopleLibrary"&lt;/span&gt;), AssemblyBuilderAccess.RunAndSave);

&lt;span class="rem"&gt;// The module builder&lt;/span&gt;
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(&lt;span class="str"&gt;"PeopleLibrary"&lt;/span&gt;, &lt;span class="str"&gt;"PeopleLibrary.dll"&lt;/span&gt;);
&lt;/pre&gt;

2.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// The person class builder&lt;/span&gt;
TypeBuilder personBuilder = modBuilder.DefineType(&lt;span class="str"&gt;"PeopleLibrary.Person"&lt;/span&gt;, TypeAttributes.Class | TypeAttributes.Public);

&lt;span class="rem"&gt;// The default constructor&lt;/span&gt;
ConstructorBuilder ctorBuilder = personBuilder.DefineDefaultConstructor(MethodAttributes.Public);
&lt;/pre&gt;

3. 

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Two fields: m_firstname, m_lastname&lt;/span&gt;
FieldBuilder fBuilderFirstName = personBuilder.DefineField(&lt;span class="str"&gt;"m_firstname"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), FieldAttributes.Private);
FieldBuilder fBuilderLastName = personBuilder.DefineField(&lt;span class="str"&gt;"m_lastname"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), FieldAttributes.Private);

&lt;span class="rem"&gt;// Two properties for this object: FirstName, LastName&lt;/span&gt;
PropertyBuilder pBuilderFirstName = personBuilder.DefineProperty(&lt;span class="str"&gt;"FirstName"&lt;/span&gt;, System.Reflection.PropertyAttributes.HasDefault, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;null&lt;/span&gt;);
PropertyBuilder pBuilderLastName = personBuilder.DefineProperty(&lt;span class="str"&gt;"LastName"&lt;/span&gt;, System.Reflection.PropertyAttributes.HasDefault, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;null&lt;/span&gt;);
&lt;/pre&gt;

4.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Custom attributes for get, set accessors&lt;/span&gt;
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName;

&lt;span class="rem"&gt;// get,set accessors for FirstName&lt;/span&gt;
MethodBuilder mGetFirstNameBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"get_FirstName"&lt;/span&gt;, getSetAttr, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), Type.EmptyTypes);

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = mGetFirstNameBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, fBuilderFirstName); &lt;span class="rem"&gt;// returning the firstname field&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);

MethodBuilder mSetFirstNameBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"set_FirstName"&lt;/span&gt;, getSetAttr, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;) });

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = mSetFirstNameBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Stfld, fBuilderFirstName); &lt;span class="rem"&gt;// setting the firstname field from the first argument (1)&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

5.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// get,set accessors for LastName&lt;/span&gt;
MethodBuilder mGetLastNameBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"get_LastName"&lt;/span&gt;, getSetAttr, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), Type.EmptyTypes);

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = mGetLastNameBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, fBuilderLastName); &lt;span class="rem"&gt;// returning the firstname field&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);

MethodBuilder mSetLastNameBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"set_LastName"&lt;/span&gt;, getSetAttr, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;) });

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = mSetLastNameBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Stfld, fBuilderLastName); &lt;span class="rem"&gt;// setting the firstname field from the first argument (1)&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

6.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Assigning get/set accessors&lt;/span&gt;
pBuilderFirstName.SetGetMethod(mGetFirstNameBuilder);
pBuilderFirstName.SetSetMethod(mSetFirstNameBuilder);

pBuilderLastName.SetGetMethod(mGetLastNameBuilder);
pBuilderLastName.SetSetMethod(mSetLastNameBuilder);
&lt;/pre&gt;

7.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Now, a custom method named GetFullName that concatenates FirstName and LastName properties&lt;/span&gt;
MethodBuilder mGetFullNameBuilder = personBuilder.DefineMethod(&lt;span class="str"&gt;"GetFullName"&lt;/span&gt;, MethodAttributes.Public, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), Type.EmptyTypes);

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = mGetFullNameBuilder.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, mGetFirstNameBuilder); &lt;span class="rem"&gt;// getting the firstname&lt;/span&gt;
ilgen.Emit(OpCodes.Ldstr, &lt;span class="str"&gt;" "&lt;/span&gt;); &lt;span class="rem"&gt;// an space&lt;/span&gt;
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, mGetLastNameBuilder); &lt;span class="rem"&gt;// getting the lastname&lt;/span&gt;

&lt;span class="rem"&gt;// We need the 'Concat' method from string type&lt;/span&gt;
MethodInfo concatMethod = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(String).GetMethod(&lt;span class="str"&gt;"Concat"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;) });

ilgen.Emit(OpCodes.Call, concatMethod); &lt;span class="rem"&gt;// calling concat and returning the result&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

8.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Another constructor that initializes firstname and lastname&lt;/span&gt;
ConstructorBuilder ctorBuilder2 = personBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;) });
ctorBuilder2.DefineParameter(1, ParameterAttributes.In, &lt;span class="str"&gt;"firstname"&lt;/span&gt;);
ctorBuilder2.DefineParameter(2, ParameterAttributes.In, &lt;span class="str"&gt;"lastname"&lt;/span&gt;);

&lt;span class="rem"&gt;// Code generation&lt;/span&gt;
ilgen = ctorBuilder2.GetILGenerator();

&lt;span class="rem"&gt;// First of all, we need to call the base constructor, &lt;/span&gt;
&lt;span class="rem"&gt;// the Object's constructor in this sample&lt;/span&gt;
Type objType = Type.GetType(&lt;span class="str"&gt;"System.Object"&lt;/span&gt;);
ConstructorInfo objCtor = objType.GetConstructor(Type.EmptyTypes);

ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, objCtor); &lt;span class="rem"&gt;// calling the Object's constructor&lt;/span&gt;

ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Call, mSetFirstNameBuilder); &lt;span class="rem"&gt;// setting the firstname field from the first argument (1)&lt;/span&gt;
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_2);
ilgen.Emit(OpCodes.Call, mSetLastNameBuilder);  &lt;span class="rem"&gt;// setting the lastname field from the second argument (2)&lt;/span&gt;
ilgen.Emit(OpCodes.Ret);
&lt;/pre&gt;

9.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Finally, create the type and save the assembly&lt;/span&gt;
personBuilder.CreateType();

asmBuilder.Save(&lt;span class="str"&gt;"PeopleLibrary.dll"&lt;/span&gt;);
&lt;/pre&gt;

10. Using the library in another project that refereces &lt;em&gt;PeopleLibrary.dll&lt;/em&gt;:

&lt;pre class="csharpcode"&gt;
Person p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"oscar"&lt;/span&gt;, &lt;span class="str"&gt;"londono"&lt;/span&gt;);

MessageBox.Show(p.GetFullName());
&lt;/pre&gt;

See &lt;a href="http://olondono.blogspot.com/2008/02/creating-code-at-runtime-part-2.html"&gt;Part 2&lt;/a&gt; and &lt;a href="http://olondono.blogspot.com/2008/02/creating-code-at-runtime-part-3.html"&gt;Part 3&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2129490894400507216?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2129490894400507216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2129490894400507216' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2129490894400507216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2129490894400507216'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/02/creating-code-at-runtime.html' title='Creating Code at Runtime / System.Reflection.Emit'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-3227559584069957093</id><published>2008-02-08T09:06:00.000-08:00</published><updated>2008-02-08T09:27:13.103-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Dynamic Code (Using Reflection)</title><content type='html'>We can use reflection to invoke code dynamically.  Here a little sample creating an &lt;em&gt;Stack&lt;/em&gt; object from the assembly &lt;em&gt;mscorlib.dll&lt;/em&gt;.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Loading the assembly&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; path = &lt;span class="str"&gt;@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll"&lt;/span&gt;;
Assembly asm = Assembly.LoadFile(path);
&amp;nbsp;
&lt;span class="rem"&gt;// Getting a stack object type&lt;/span&gt;
Type stackType = asm.GetType(&lt;span class="str"&gt;"System.Collections.Stack"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Building the constructor call&lt;/span&gt;
Type[] argumentTypes = Type.EmptyTypes;
ConstructorInfo ctor = stackType.GetConstructor(argumentTypes);
&amp;nbsp;
&lt;span class="kwrd"&gt;object&lt;/span&gt; stackObj = ctor.Invoke(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { });
&amp;nbsp;
&lt;span class="rem"&gt;// Calling the Push method and passing by parameters the value &lt;/span&gt;
&lt;span class="rem"&gt;// we want to push in the stack&lt;/span&gt;
MethodInfo mpush = stackType.GetMethod(&lt;span class="str"&gt;"Push"&lt;/span&gt;);
mpush.Invoke(stackObj, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { &lt;span class="str"&gt;"One"&lt;/span&gt; });
mpush.Invoke(stackObj, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { &lt;span class="str"&gt;"Two"&lt;/span&gt; });
mpush.Invoke(stackObj, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { &lt;span class="str"&gt;"Three"&lt;/span&gt; });
&amp;nbsp;
&lt;span class="rem"&gt;// Getting a property value (Count)&lt;/span&gt;
PropertyInfo propInfo = stackType.GetProperty(&lt;span class="str"&gt;"Count"&lt;/span&gt;);
&lt;span class="kwrd"&gt;int&lt;/span&gt; count = (&lt;span class="kwrd"&gt;int&lt;/span&gt;)propInfo.GetValue(stackObj, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
&amp;nbsp;
MessageBox.Show(count.ToString());
&amp;nbsp;
&lt;span class="rem"&gt;// Getting values using the Pop method&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; s;
&amp;nbsp;
MethodInfo mpop = stackType.GetMethod(&lt;span class="str"&gt;"Pop"&lt;/span&gt;);
s = mpop.Invoke(stackObj, &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;;
MessageBox.Show(s);
s = mpop.Invoke(stackObj, &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;;
MessageBox.Show(s);
s = mpop.Invoke(stackObj, &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;;
MessageBox.Show(s);
&lt;/pre&gt;

We can also create the object by using the &lt;em&gt;Activator&lt;/em&gt; object:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;object&lt;/span&gt; stackObj = Activator.CreateInstance(stackType);
&lt;/pre&gt;

If we need to create the object using another constructor different from the default constructor, we can achieve this:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt; initialCapacity = 10;
&amp;nbsp;
&lt;span class="rem"&gt;// Building the constructor call with one parameter type of integer&lt;/span&gt;
Type[] argumentTypes = &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt;) };
ConstructorInfo ctor = stackType.GetConstructor(argumentTypes);
&amp;nbsp;
&lt;span class="rem"&gt;// Creating the object&lt;/span&gt;
&lt;span class="kwrd"&gt;object&lt;/span&gt; stackObj = ctor.Invoke(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { initialCapacity });
&lt;/pre&gt;

Or using the &lt;em&gt;Activator&lt;/em&gt;:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt; initialCapacity = 10;
&amp;nbsp;
&lt;span class="kwrd"&gt;object&lt;/span&gt; stackObj = Activator.CreateInstance(stackType, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { initialCapacity });
&lt;/pre&gt;

For calling static methods, we need to pass &lt;em&gt;null&lt;/em&gt; as object paramenter when using the &lt;em&gt;Invoke&lt;/em&gt; method, here an example calling the &lt;em&gt;MessageBox.Show&lt;/em&gt; method:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Loading the assembly&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; path = &lt;span class="str"&gt;@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll"&lt;/span&gt;;
Assembly myAsm = Assembly.LoadFile(path);
&amp;nbsp;
&lt;span class="rem"&gt;// Getting the type MessageBox&lt;/span&gt;
Type msgBox = myAsm.GetType(&lt;span class="str"&gt;"System.Windows.Forms.MessageBox"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Invoking the static method 'Show'&lt;/span&gt;
MethodInfo showMethod = msgBox.GetMethod(&lt;span class="str"&gt;"Show"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;) });
showMethod.Invoke(&lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { &lt;span class="str"&gt;"Hello world!"&lt;/span&gt; });
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3227559584069957093?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3227559584069957093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3227559584069957093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3227559584069957093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3227559584069957093'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/02/dynamic-code-using-reflection.html' title='Dynamic Code (Using Reflection)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6871585439338441763</id><published>2008-02-07T07:24:00.000-08:00</published><updated>2008-02-07T08:55:15.563-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics AX'/><category scheme='http://www.blogger.com/atom/ns#' term='Axapta'/><title type='text'>How show a popup menu in AX/Axapta</title><content type='html'>In the following sample, I have duplicated the &lt;em&gt;sysAOT&lt;/em&gt; form, and I have overrode the &lt;em&gt;context&lt;/em&gt; method for the tree control.  Here the code to show the &lt;em&gt;system context menu&lt;/em&gt; for any selected &lt;em&gt;treeNode&lt;/em&gt;.

&lt;pre class="csharpcode"&gt;
PopupMenu       popupMenu;
SysContextMenu  sysContextMenu;
&lt;span class="kwrd"&gt;int&lt;/span&gt; idx = tree.getFirstSelected();
TreeNode treeNode = tree.getItem(idx).data();
&amp;nbsp;
&lt;span class="rem"&gt;// add some custom menu items&lt;/span&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt; editMenu;
&lt;span class="kwrd"&gt;int&lt;/span&gt; choice;
;
&amp;nbsp;
&lt;span class="rem"&gt;// current selected treeNode is valid ?&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (treeNode == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    &lt;span class="kwrd"&gt;return&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// create the SysContextMenu for this TreeNode&lt;/span&gt;
sysContextMenu = &lt;span class="kwrd"&gt;new&lt;/span&gt; SysContextMenuTreeNode(treeNode);
&amp;nbsp;
&lt;span class="rem"&gt;// System API call to build the popup menu&lt;/span&gt;
popupMenu = sysContextMenu.buildMenu(&lt;span class="kwrd"&gt;this&lt;/span&gt;.hWnd());
&amp;nbsp;
&lt;span class="rem"&gt;// Add a custom edit menu&lt;/span&gt;
popupMenu.insertBreak();
editMenu = popupMenu.insertItem(&lt;span class="str"&gt;"Edit"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// showing menu&lt;/span&gt;
choice = popupMenu.draw();
&amp;nbsp;
&lt;span class="rem"&gt;// Showing and processing this popupMenu&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!sysContextMenu.runMenu(choice, sysContextMenu))
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (choice == editMenu)
    {
        SysInfoAction_Editor::newOpen(treeNode.treeNodePath()).run();
    }
}
&lt;/pre&gt;

But, looking in depth, I found that the &lt;em&gt;sysAotFind&lt;/em&gt; form can be used to get some practical sample on how we can create our custom popup menu.  Here an adapted version of that code to the previous &lt;em&gt;SysAOT2&lt;/em&gt; form(method context within control tree):

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// current selected treeNode&lt;/span&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt; idx = tree.getFirstSelected();
TreeNode treeNode = tree.getItem(idx).data();
&amp;nbsp;
&lt;span class="rem"&gt;// We want to build, a popup menu, with a custom submenu and another&lt;/span&gt;
&lt;span class="rem"&gt;// sysContextMenu as submenu (add-ins menu item)&lt;/span&gt;
PopupMenu       popupMenu      = &lt;span class="kwrd"&gt;new&lt;/span&gt; PopupMenu(&lt;span class="kwrd"&gt;this&lt;/span&gt;.hWnd());
PopupMenu       copyMenu       = &lt;span class="kwrd"&gt;new&lt;/span&gt; PopupMenu(&lt;span class="kwrd"&gt;this&lt;/span&gt;.hWnd(), popupMenu);
PopupMenu       subSysContextMenu;
SysContextMenu  sysContextMenu;
&amp;nbsp;
&lt;span class="rem"&gt;// Menu options&lt;/span&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             open;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             editMethod;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             copyName;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             copyPath;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             copyFullPath;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             copyAll;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             choice;
&lt;span class="kwrd"&gt;int&lt;/span&gt;             find;
;
&amp;nbsp;
&lt;span class="rem"&gt;// current selected treeNode is valid ?&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (treeNode == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    &lt;span class="kwrd"&gt;return&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// create the SysContextMenu for this TreeNode&lt;/span&gt;
sysContextMenu = &lt;span class="kwrd"&gt;new&lt;/span&gt; SysContextMenuTreeNode(treeNode);
&amp;nbsp;
&lt;span class="rem"&gt;//---------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Building the menu&lt;/span&gt;
open = popupMenu.insertItem(&lt;span class="str"&gt;"Open"&lt;/span&gt;);
popupMenu.insertBreak();
editMethod = popupMenu.insertItem(&lt;span class="str"&gt;"Edit"&lt;/span&gt;);
&amp;nbsp;
copyName        = copyMenu.insertItem(&lt;span class="str"&gt;"Copy Name"&lt;/span&gt;);
copyPath        = copyMenu.insertItem(&lt;span class="str"&gt;"Copy Path"&lt;/span&gt;);
copyFullPath    = copyMenu.insertItem(&lt;span class="str"&gt;"Copy FullPath"&lt;/span&gt;);
copyAll         = copyMenu.insertItem(&lt;span class="str"&gt;"Copy All"&lt;/span&gt;);
&amp;nbsp;
popupMenu.insertPopupMenu(&lt;span class="str"&gt;"Copy"&lt;/span&gt;, copyMenu);
popupMenu.insertBreak();
&amp;nbsp;
find = popupMenu.insertItem(&lt;span class="str"&gt;"Find"&lt;/span&gt;);
popupMenu.insertBreak();
&amp;nbsp;
subSysContextMenu = sysContextMenu.buildMenu(&lt;span class="kwrd"&gt;this&lt;/span&gt;.hWnd(), popupMenu);
popupMenu.insertPopupMenu(&lt;span class="str"&gt;"Add-ins"&lt;/span&gt;, subSysContextMenu);
&lt;span class="rem"&gt;//---------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Now, showing the popup menu&lt;/span&gt;
choice = popupMenu.draw();
&amp;nbsp;
&lt;span class="rem"&gt;// processing option&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!sysContextMenu.runMenu(choice, sysContextMenu))
{
    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (choice)
    {
        &lt;span class="kwrd"&gt;case&lt;/span&gt; open:
            &lt;span class="rem"&gt;// to implement&lt;/span&gt;
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
&amp;nbsp;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; editMethod:
            SysInfoAction_Editor::newOpen(treeNode.treeNodePath()).run();
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
&amp;nbsp;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; find:
            &lt;span class="rem"&gt;// to implement&lt;/span&gt;
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
&amp;nbsp;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; copyName, copyPath, copyFullPath, copyAll:
            &lt;span class="rem"&gt;// to implement&lt;/span&gt;
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6871585439338441763?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6871585439338441763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6871585439338441763' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6871585439338441763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6871585439338441763'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/02/how-show-popup-menu-in-axaxapta.html' title='How show a popup menu in AX/Axapta'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5923011272894330132</id><published>2008-01-30T14:49:00.000-08:00</published><updated>2008-02-09T09:20:45.554-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Reflection</title><content type='html'>&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Loading the current assembly&lt;/span&gt;
Assembly myAsm = Assembly.GetExecutingAssembly();
&amp;nbsp;
&lt;span class="rem"&gt;// Showing some properties&lt;/span&gt;
MessageBox.Show(myAsm.FullName);
MessageBox.Show(myAsm.Location);
&amp;nbsp;
&lt;span class="rem"&gt;// Getting some assembly attribute&lt;/span&gt;
Type attrType = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(AssemblyDescriptionAttribute);
&lt;span class="kwrd"&gt;object&lt;/span&gt;[] attrs = myAsm.GetCustomAttributes(attrType, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Attribute attr &lt;span class="kwrd"&gt;in&lt;/span&gt; attrs)
{
    AssemblyDescriptionAttribute desc = attr &lt;span class="kwrd"&gt;as&lt;/span&gt; AssemblyDescriptionAttribute;
    MessageBox.Show(desc.Description);
}
&amp;nbsp;
&lt;span class="rem"&gt;// Getting types in this assembly&lt;/span&gt;
Type[] types = myAsm.GetTypes();
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Type t &lt;span class="kwrd"&gt;in&lt;/span&gt; types)
    MessageBox.Show(t.ToString());
&amp;nbsp;
&lt;span class="rem"&gt;// Getting more information about an object&lt;/span&gt;
MemberInfo[] minfos = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Person).GetMembers();
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (MemberInfo mi &lt;span class="kwrd"&gt;in&lt;/span&gt; minfos)
    MessageBox.Show(mi.ToString());
&amp;nbsp;
&lt;span class="rem"&gt;// Getting attributes for an object&lt;/span&gt;
Type tstring = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Attribute attr &lt;span class="kwrd"&gt;in&lt;/span&gt; tstring.GetCustomAttributes(&lt;span class="kwrd"&gt;false&lt;/span&gt;))
    MessageBox.Show(attr.ToString()); &lt;span class="rem"&gt;//.GetType().Name);&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Assembly static methods&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;

&lt;em&gt;GetAssembly&lt;br&gt;
GetCallingAssembly&lt;br&gt;
GetEntryAssembly&lt;br&gt;
GetExecutingAssembly&lt;br&gt;
Load&lt;br&gt;
LoadFile&lt;br&gt;
LoadFrom&lt;br&gt;
ReflectionOnlyLoad&lt;br&gt;
ReflectionOnlyLoadFrom&lt;/em&gt;&lt;br&gt;&lt;br&gt;

Some useful methods:

&lt;em&gt;Location&lt;br&gt;
FullName&lt;br&gt;
GetCustomAttributes&lt;br&gt;
GetExportedTypes&lt;br&gt;
GetModules/GetModule&lt;br&gt;
GetTypes&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Type class properties:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;em&gt;Assembly&lt;br&gt;
Attributes&lt;br&gt;
IsClass&lt;br&gt;
IsEnum&lt;br&gt;
IsInterface&lt;br&gt;
IsPrimitive&lt;br&gt;
... and others&lt;br&gt;
&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Type class methods:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;em&gt;GetConstructor/GetConstructors&lt;br&gt;
GetEvent/GetEvents&lt;br&gt;
GetField/GetFields&lt;br&gt;
GetMember/GetMembers&lt;br&gt;
GetMethod/GetMethods&lt;br&gt;
GetProperty/GetProperties&lt;br&gt;
... and others&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;MemberInfo derived classes:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;em&gt;ConstructorInfo&lt;br&gt;
EventInfo&lt;br&gt;
FieldInfo&lt;br&gt;
LocalVariableInfo&lt;br&gt;
MethodBase&lt;br&gt;
MethodInfo&lt;br&gt;
PropertyInfo&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;BindingFlags enumeration:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;em&gt;DeclaredOnly&lt;/em&gt; - Members directly declared on the specific type are included. Inherited members are ignored.&lt;br&gt;
&lt;em&gt;FlattenHierarchy&lt;/em&gt; - Declared and inherited members should be returned, but also returns protected members.&lt;br&gt;
&lt;em&gt;IgnoreCase&lt;/em&gt; - A case-insensitive matching of the member name should be used.&lt;br&gt;
&lt;em&gt;Instance&lt;/em&gt; - Members that are part of an instance of type will be included.&lt;br&gt;
&lt;em&gt;NonPublic&lt;/em&gt; - Members that are not public are included.&lt;br&gt;
&lt;em&gt;Public&lt;/em&gt; - Members that are public are included.&lt;br&gt;
&lt;em&gt;Static&lt;/em&gt; - Members that are defined as static are included.&lt;br&gt;

Sample:

&lt;pre class="csharpcode"&gt;
Type tperson = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Person);
&amp;nbsp;
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
&amp;nbsp;
MemberInfo[] members = tperson.GetMembers(flags);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (MemberInfo member &lt;span class="kwrd"&gt;in&lt;/span&gt; members)
    MessageBox.Show(member.Name);
&lt;/pre&gt;

More information: &lt;a href="http://olondono.blogspot.com/2007/11/attributes-example-from-csharp-online.html"&gt;Attributes (An example)&lt;/a&gt;&lt;br&gt;&lt;br&gt;

&lt;a href="http://olondono.blogspot.com/2007/11/simple-activities-manager-this-is.html"&gt;A simple activities manager&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5923011272894330132?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5923011272894330132/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5923011272894330132' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5923011272894330132'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5923011272894330132'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/reflection.html' title='Reflection'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-272114533851587476</id><published>2008-01-29T18:32:00.000-08:00</published><updated>2008-02-09T09:25:38.469-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>P/Invoke - Platform Invoke</title><content type='html'>We encapsulates API calls by using a class and declaring &lt;em&gt;static&lt;/em&gt; methods with the &lt;em&gt;DllImport&lt;/em&gt; Attribute. For data convertion with use the MarshalAs attribute. For structures, we use the &lt;em&gt;LayoutKind&lt;/em&gt; attribute (normally the &lt;em&gt;Layout.Sequential&lt;/em&gt; is used).

Here an example how we can invoke the API MessageBox:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// API class declaration&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Win32Api
{
    [DllImport(&lt;span class="str"&gt;"user32.dll"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; IntPtr MessageBox(IntPtr hWnd, String text, String caption, &lt;span class="kwrd"&gt;uint&lt;/span&gt; type);
}
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span class="rem"&gt;// Calling the API Messagebox&lt;/span&gt;
    Win32Api.MessageBox(&lt;span class="kwrd"&gt;this&lt;/span&gt;.Handle, &lt;span class="str"&gt;"test Message"&lt;/span&gt;, &lt;span class="str"&gt;"caption"&lt;/span&gt;, 64);
}
&lt;/pre&gt;

Some fields for DllImport attribute:&lt;br&gt;&lt;br&gt;

&lt;em&gt;CallingConvention&lt;/em&gt; - (Winapi, Cdecl, StdCall, ThisCall, FastCall). Winapi is default por windows APIs and Cdecl for Windows CE.NET.&lt;br&gt;&lt;br&gt;

&lt;em&gt;CharSet&lt;/em&gt; - How string arguments should be marshaled (Ansi, Unicode, None, Auto)&lt;br&gt;&lt;br&gt;

&lt;em&gt;EntryPoint&lt;/em&gt; - DLL entry point, this allows us for use a different name for the API in our class. &lt;em&gt;See bellow&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;em&gt;PreserveSig&lt;/em&gt; - The signature should be transformed into an unmanaged signature that returns an HRESULT and has an additional [out, retval] argument for the return value. This mean, the function will return an HRESULT instead of thrown an exception when an error occurs. More information see &lt;a href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.preservesig.aspx"&gt;MSDN&lt;/a&gt;.&lt;br&gt;&lt;br&gt;

&lt;em&gt;SetLastError&lt;/em&gt; - Enable the caller to use the &lt;em&gt;Marshal.GetLasWin32Error&lt;/em&gt; API function to determine whether an error ocurred while executing the method.&lt;br&gt;&lt;br&gt;


Samples:

&lt;pre class="csharpcode"&gt;
[DllImport(&lt;span class="str"&gt;"msvcrt.dll"&lt;/span&gt;, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; printf(String format, &lt;span class="kwrd"&gt;int&lt;/span&gt; i, &lt;span class="kwrd"&gt;double&lt;/span&gt; d);

[DllImport(&lt;span class="str"&gt;"user32.dll"&lt;/span&gt;, CharSet = CharSet.Auto, EntryPoint = &lt;span class="str"&gt;"MessageBox"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; MyNewMessageBoxMethod(IntPtr hWnd, String text, String caption, &lt;span class="kwrd"&gt;uint&lt;/span&gt; type);
&lt;/pre&gt;

More about PreserveSig:

Unlike COM Interop scenarios, PInvoke signatures have &lt;em&gt;PreserveSig&lt;/em&gt; semantics by default. For example, in the &lt;em&gt;IOleClientSite&lt;/em&gt; interface, we need to preserve the signature:

&lt;pre class="csharpcode"&gt;
[ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;), Guid(&lt;span class="str"&gt;"00000118-0000-0000-C000-000000000046"&lt;/span&gt;), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IOleClientSite
{

    [&lt;span class="kwrd"&gt;return&lt;/span&gt;: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    &lt;span class="kwrd"&gt;int&lt;/span&gt; SaveObject();

    [&lt;span class="kwrd"&gt;return&lt;/span&gt;: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    &lt;span class="kwrd"&gt;int&lt;/span&gt; GetMoniker(
        [In, MarshalAs(UnmanagedType.U4)]          &lt;span class="kwrd"&gt;int&lt;/span&gt; dwAssign,
        [In, MarshalAs(UnmanagedType.U4)]          &lt;span class="kwrd"&gt;int&lt;/span&gt; dwWhichMoniker,
        [Out, MarshalAs(UnmanagedType.Interface)] &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; ppmk);
        
    [&lt;span class="kwrd"&gt;return&lt;/span&gt;: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    &lt;span class="kwrd"&gt;int&lt;/span&gt; GetContainer([MarshalAs(UnmanagedType.Interface)] &lt;span class="kwrd"&gt;out&lt;/span&gt; IOleContainer container);

    [&lt;span class="kwrd"&gt;return&lt;/span&gt;: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    &lt;span class="kwrd"&gt;int&lt;/span&gt; ShowObject();

    [&lt;span class="kwrd"&gt;return&lt;/span&gt;: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    &lt;span class="kwrd"&gt;int&lt;/span&gt; OnShowWindow(
        [In, MarshalAs(UnmanagedType.I4)] &lt;span class="kwrd"&gt;int&lt;/span&gt; fShow);

    [&lt;span class="kwrd"&gt;return&lt;/span&gt;: MarshalAs(UnmanagedType.I4)]
    [PreserveSig]
    &lt;span class="kwrd"&gt;int&lt;/span&gt; RequestNewObjectLayout();
}
&lt;/pre&gt;

More about &lt;em&gt;PreserveSig&lt;/em&gt; in the &lt;a href="http://blogs.msdn.com/adam_nathan/archive/2003/04/30/56646.aspx"&gt;Adam Nathan's Blog&lt;/a&gt;.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Passing structures:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

When passing structures or classes to unmanaged code using platform invoke, you must provide additional information to preserve the original layout and alignment. Here some examples from &lt;a href="http://msdn2.microsoft.com/en-us/library/awbckfbz.aspx"&gt;MSDN&lt;/a&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[StructLayout(LayoutKind.Sequential)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; Point
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; x;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; y;
}  

[StructLayout(LayoutKind.Explicit)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; Rect
{
    [FieldOffset(0)] &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; left;
    [FieldOffset(4)] &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; top;
    [FieldOffset(8)] &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; right;
    [FieldOffset(12)] &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; bottom;
}  

&lt;span class="kwrd"&gt;class&lt;/span&gt; Win32API
{
    [DllImport(&lt;span class="str"&gt;"User32.dll"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; PtInRect(&lt;span class="kwrd"&gt;ref&lt;/span&gt; Rect r, Point p);
}
&lt;/pre&gt;

&lt;strong&gt;Callback functions:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

For invoking API functions that are expecting a callback function, we need to declare one delegate function and one method conforms the delegate declaration. Here an example from &lt;a href="http://msdn2.microsoft.com/en-us/library/843s5s5x.aspx"&gt;MSDN&lt;/a&gt; that enumerates every opened window in the system:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// The callback delegate declaration&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;delegate&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; theCallBack(&lt;span class="kwrd"&gt;int&lt;/span&gt; hwnd, &lt;span class="kwrd"&gt;int&lt;/span&gt; lParam);

&lt;span class="rem"&gt;// The API wrapper&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; EnumReportApp
{
    [DllImport(&lt;span class="str"&gt;"user32"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; EnumWindows(theCallBack x, &lt;span class="kwrd"&gt;int&lt;/span&gt; y);

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Run()
    {
        &lt;span class="rem"&gt;// Here our callback&lt;/span&gt;
        theCallBack myCallBack = &lt;span class="kwrd"&gt;new&lt;/span&gt; theCallBack(EnumReportApp.Report);
        EnumWindows(myCallBack, 0);
    }

    &lt;span class="rem"&gt;// This is the callback that EnumWindows will call&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; Report(&lt;span class="kwrd"&gt;int&lt;/span&gt; hwnd, &lt;span class="kwrd"&gt;int&lt;/span&gt; lParam)
    {
        Console.Write(&lt;span class="str"&gt;"Window handle is "&lt;/span&gt;);
        Console.WriteLine(hwnd);
        
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
    }
}

&lt;span class="rem"&gt;// Main program&lt;/span&gt;
&lt;span class="kwrd"&gt;class&lt;/span&gt; Program
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main()
    {
        EnumReportApp.Run();
    }
}&lt;/pre&gt;


&lt;strong&gt;Marshaling:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

For APIs returning string values, is a best practice use the &lt;em&gt;StringBuilder&lt;/em&gt; instead of normal strings classes when they expect a reference string type.

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Win32Api
{
    [DllImport(&lt;span class="str"&gt;"user32.dll"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; IntPtr GetForegroundWindow();
    
    [DllImport(&lt;span class="str"&gt;"user32.dll"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; Int32 GetWindowText(IntPtr hWnd, StringBuilder textValue, Int32 counter);

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetForegroupWindowText()
    {
        &lt;span class="rem"&gt;// Our string builder prefixed to 256 characters&lt;/span&gt;
        StringBuilder sb = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder(256);
        IntPtr hwnd = GetForegroundWindow();

        GetWindowText(hwnd, sb, 256);

        &lt;span class="kwrd"&gt;return&lt;/span&gt; sb.ToString();
    }
}
&lt;/pre&gt;

&lt;em&gt;"For example, you can marshal a string to unmanaged code as either a LPStr, a LPWStr, a LPTStr, or a BStr. By default, the common language runtime marshals a string parameter as a BStr to COM methods. You can apply the MarshalAsAttribute attribute to an individual field or parameter to cause that particular string to be marshaled as a LPStr instead of a BStr."&lt;/em&gt; - from MSDN

&lt;pre class="csharpcode"&gt;
[DllImport(&lt;span class="str"&gt;"user32.dll"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; MessageBoxW(
    IntPtr hWnd,
    [MarshalAs(UnmanagedType.LPWStr)] String text,
    [MarshalAs(UnmanagedType.LPWStr)] String caption,
    &lt;span class="kwrd"&gt;int&lt;/span&gt; type);
&lt;/pre&gt;

More information about Marshaling with P/Invoke in &lt;a href="http://msdn2.microsoft.com/en-us/library/fzhhdwae.aspx"&gt;MSDN&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-272114533851587476?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/272114533851587476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=272114533851587476' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/272114533851587476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/272114533851587476'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/pinvoke-platform-invoke.html' title='P/Invoke - Platform Invoke'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-3618860253746286638</id><published>2008-01-29T14:47:00.000-08:00</published><updated>2008-02-09T09:27:49.892-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>COM Interop</title><content type='html'>For exposing .NET classes as COM objects:

1. Set the assembly attribute &lt;em&gt;ComVisible&lt;/em&gt; equals &lt;em&gt;true&lt;/em&gt;:
&lt;pre class="csharpcode"&gt;
[assembly: ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;/pre&gt;

2. Set the project for &lt;em&gt;"Register for COM Interop"&lt;/em&gt;: Project's Properties -&gt; Build tab -&gt; Output group -&gt; check box: Register for COM Interop.&lt;br&gt;&lt;br&gt;

3. Create public classes and use the &lt;em&gt;ComVisible&lt;/em&gt; attribute to hide some members and functions.

&lt;pre class="csharpcode"&gt;
[ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person : IPerson
{
    [ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }
&amp;nbsp;
    [ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName { get; set; }
&amp;nbsp;
    [ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime BirthDay { get; set; }
&amp;nbsp;
    [ComVisible(&lt;span class="kwrd"&gt;false&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Age { get; set; }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
    }
&amp;nbsp;
    [ComVisible(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFullName()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; getFullNameInt();
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; getFullNameInt()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Name + &lt;span class="str"&gt;" "&lt;/span&gt; + LastName;
    }
&amp;nbsp;
    [ComVisible(&lt;span class="kwrd"&gt;false&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; GetAge()
    {
        Age = DateTime.Now.Year - BirthDay.Year - 1;
&amp;nbsp;       
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Age;
    }
}
&lt;/pre&gt;

You can use this class for &lt;strong&gt;Late Bounding&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;

And, what about &lt;strong&gt;Early Bounding&lt;/strong&gt;?&lt;br&gt;&lt;br&gt;

If we want to expose our classes for &lt;em&gt;Early Bounding&lt;/em&gt;, the best practice is:&lt;br&gt;&lt;br&gt;

1. Declare interfaces that represents our objects.&lt;br&gt;
2. Implement interfaces in public classes.&lt;br&gt;
3. Set some attributes for better COM objects exposing:&lt;br&gt;
   3.a Use an specific &lt;em&gt;Guid&lt;/em&gt; for every interface and every class&lt;br&gt;
   3.b Declare the interface as &lt;em&gt;InterfaceIsDual&lt;/em&gt;&lt;br&gt;
   3.c Qualify every member and function with its &lt;em&gt;DispId&lt;/em&gt;&lt;br&gt;
   3.d Implement the class with the &lt;em&gt;ClassInterfaceType=None&lt;/em&gt;&lt;br&gt;
   3.e Set the &lt;em&gt;ProgId&lt;/em&gt; for the class&lt;br&gt;&lt;br&gt;

Example:

&lt;pre class="csharpcode"&gt;
[Guid(&lt;span class="str"&gt;"568680FF-FBF8-4b84-A8D6-F430197870F9"&lt;/span&gt;)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IPerson
{
    [DispId(1)]
    &lt;span class="kwrd"&gt;string&lt;/span&gt; Name{get;set;}
&amp;nbsp;
    [DispId(2)]
    &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName{get;set;}
&amp;nbsp;
    [DispId(3)]
    DateTime BirthDay { get; set; }
&amp;nbsp;
    [DispId(4)]
    &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFullName();
&amp;nbsp;
    [DispId(5)]
    &lt;span class="kwrd"&gt;int&lt;/span&gt; GetAge();
}
&amp;nbsp;
[Guid(&lt;span class="str"&gt;"D798A2FC-01A6-4c97-AC0F-703C3B2DBC81"&lt;/span&gt;),
ProgId(&lt;span class="str"&gt;"ComTestLibrary.Person"&lt;/span&gt;),
ClassInterface(ClassInterfaceType.None)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person : IPerson
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime BirthDay { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Age { get; set; }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFullName()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; getFullNameInt();
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; getFullNameInt()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Name + &lt;span class="str"&gt;" "&lt;/span&gt; + LastName;
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; GetAge()
    {
        Age = DateTime.Now.Year - BirthDay.Year - 1;
&amp;nbsp;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Age;
    }
}
&lt;/pre&gt;

This is old-versions compatible and we are able to add more properties and methods with its own &lt;em&gt;DispId&lt;/em&gt;, so we don't need to recompile old consumers for this COM component.&lt;br&gt;&lt;br&gt;

NOTE: Avoid use the &lt;em&gt;ClassInterfaceType.AutoDual&lt;/em&gt; attribute because it is not old-versions compatible.  Every time you change your .NET class, you must recompile COM clients.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Exposing .NET Events to COM:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

For exposing events from .NET to COM, we need to add a new interface that define the events we want to dispatch.  Then, we need to change the class according to the events we are exposing (the name must be equals), take a look:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// The new interface declaration&lt;/span&gt;
[Guid(&lt;span class="str"&gt;"866226CC-679E-4ce7-B527-5A80D6950278"&lt;/span&gt;)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IPersonEvents
{
    [DispId(1)]
    &lt;span class="kwrd"&gt;void&lt;/span&gt; BeforeGetFullName(&lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;string&lt;/span&gt; lastname); &lt;span class="rem"&gt;// Event declaration&lt;/span&gt;
&amp;nbsp;
    [DispId(2)]
    &lt;span class="kwrd"&gt;void&lt;/span&gt; OtherEventWithoutParameters(); &lt;span class="rem"&gt;// Event declaration&lt;/span&gt;
}
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
[Guid(&lt;span class="str"&gt;"D798A2FC-01A6-4c97-AC0F-703C3B2DBC81"&lt;/span&gt;),
ProgId(&lt;span class="str"&gt;"ComTestLibrary.Person"&lt;/span&gt;),
ComSourceInterfaces(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IPersonEvents)), &lt;span class="rem"&gt;// Events interface implementation&lt;/span&gt;
ClassInterface(ClassInterfaceType.None)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person : IPerson
{
    &lt;span class="rem"&gt;// Delegates declaration&lt;/span&gt;
    [ComVisible(&lt;span class="kwrd"&gt;false&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;delegate&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BeforeGetFullNameHandler(&lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;string&lt;/span&gt; lastname);
    [ComVisible(&lt;span class="kwrd"&gt;false&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;delegate&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OtherEventWithoutParametersHandler();
&amp;nbsp;
    ...
&amp;nbsp;
    &lt;span class="rem"&gt;// Our events. The name must match to the definition in &lt;/span&gt;
    &lt;span class="rem"&gt;// the interface we are implementing&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; BeforeGetFullNameHandler BeforeGetFullName;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; OtherEventWithoutParametersHandler OtherEventWithoutParameters;
&amp;nbsp;
    ...
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetFullName()
    {
        &lt;span class="rem"&gt;// Launching events&lt;/span&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (BeforeGetFullName != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            BeforeGetFullName(Name, LastName);
&amp;nbsp;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (OtherEventWithoutParameters != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            OtherEventWithoutParameters();
&amp;nbsp;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; getFullNameInt();
    }
&amp;nbsp;
    ...
}
&lt;/pre&gt;

We can consume events in some languaje like VB 6.0:

&lt;pre&gt;
Dim WithEvents c As ComTestLibrary.Person
&amp;nbsp;
Private Sub c_BeforeGetFullName(ByVal Name As String, ByVal LastName As String)
    MsgBox "Name = " &amp; Name &amp; " LastName = " &amp; LastName
End Sub
&amp;nbsp;
Private Sub c_OtherEventWithoutParameters()
    MsgBox "Event without parameters"
End Sub
&amp;nbsp;
Private Sub Command1_Click()
    If (c Is Nothing) Then
        Set c = New ComTestLibrary.Person
    End If
&amp;nbsp;    
    c.Name = "oscar"
    c.LastName = "londono"
&amp;nbsp;    
    MsgBox c.GetFullName
&amp;nbsp;    
End Sub
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3618860253746286638?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3618860253746286638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3618860253746286638' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3618860253746286638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3618860253746286638'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/com-interop.html' title='COM Interop'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5108847806198198009</id><published>2008-01-28T14:47:00.001-08:00</published><updated>2008-02-09T09:30:29.415-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Encrypting and Decrypting Data</title><content type='html'>Encrypting and decrypting data:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Test data&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; data = &lt;span class="str"&gt;"testing data for encryption-12356"&lt;/span&gt;;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] utfdata = Encoding.UTF8.GetBytes(data);
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] saltBytes = Encoding.UTF8.GetBytes(&lt;span class="str"&gt;"this my salt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Our symmetric encryption algorithm&lt;/span&gt;
RijndaelManaged aes = &lt;span class="kwrd"&gt;new&lt;/span&gt; RijndaelManaged();
&amp;nbsp;
&lt;span class="rem"&gt;// We're using the PBKDF2 standard for password-based key generation&lt;/span&gt;
Rfc2898DeriveBytes rfc = &lt;span class="kwrd"&gt;new&lt;/span&gt; Rfc2898DeriveBytes(&lt;span class="str"&gt;"password"&lt;/span&gt;, saltBytes);
&amp;nbsp;
&lt;span class="rem"&gt;// Setting our parameters&lt;/span&gt;
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
aes.KeySize = aes.LegalKeySizes[0].MaxSize;
&amp;nbsp;
aes.Key = rfc.GetBytes(aes.KeySize / 8);
aes.IV = rfc.GetBytes(aes.BlockSize / 8);
&amp;nbsp;
&lt;span class="rem"&gt;// Encryption&lt;/span&gt;
ICryptoTransform encryptTransf = aes.CreateEncryptor();
&amp;nbsp;
&lt;span class="rem"&gt;// Output stream, can be also a FileStream&lt;/span&gt;
MemoryStream encryptStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
CryptoStream encryptor = &lt;span class="kwrd"&gt;new&lt;/span&gt; CryptoStream(encryptStream, encryptTransf, CryptoStreamMode.Write);
&amp;nbsp;
encryptor.Write(utfdata, 0, utfdata.Length);
encryptor.FlushFinalBlock();
encryptor.Close();
&amp;nbsp;
&lt;span class="rem"&gt;// Showing our encrypted content&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] encryptBytes = encryptStream.ToArray();
MessageBox.Show(UTF8Encoding.UTF8.GetString(encryptBytes));
&amp;nbsp;
&lt;span class="rem"&gt;// Now, decryption&lt;/span&gt;
ICryptoTransform decryptTrans = aes.CreateDecryptor();
&amp;nbsp;
&lt;span class="rem"&gt;// Output stream, can be also a FileStream&lt;/span&gt;
MemoryStream decryptStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
CryptoStream decryptor = &lt;span class="kwrd"&gt;new&lt;/span&gt; CryptoStream(decryptStream, decryptTrans, CryptoStreamMode.Write);
&amp;nbsp;
decryptor.Write(encryptBytes, 0, encryptBytes.Length);
decryptor.Flush();
decryptor.Close();
&amp;nbsp;
&lt;span class="rem"&gt;// Showing our decrypted content&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] decryptBytes = decryptStream.ToArray();
MessageBox.Show(UTF8Encoding.UTF8.GetString(decryptBytes));
&lt;/pre&gt;

Encrypting and decrypting files:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Test data&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] saltBytes = Encoding.UTF8.GetBytes(&lt;span class="str"&gt;"this my salt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Our symmetric encryption algorithm&lt;/span&gt;
RijndaelManaged aes = &lt;span class="kwrd"&gt;new&lt;/span&gt; RijndaelManaged();
&amp;nbsp;
&lt;span class="rem"&gt;// We're using the PBKDF2 standard for password-based key generation&lt;/span&gt;
Rfc2898DeriveBytes rfc = &lt;span class="kwrd"&gt;new&lt;/span&gt; Rfc2898DeriveBytes(&lt;span class="str"&gt;"password"&lt;/span&gt;, saltBytes);
&amp;nbsp;
&lt;span class="rem"&gt;// Setting our parameters&lt;/span&gt;
aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
aes.KeySize = aes.LegalKeySizes[0].MaxSize;
&amp;nbsp;
aes.Key = rfc.GetBytes(aes.KeySize / 8);
aes.IV = rfc.GetBytes(aes.BlockSize / 8);
&amp;nbsp;
&lt;span class="rem"&gt;//----------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Encryption&lt;/span&gt;
ICryptoTransform encryptTransf = aes.CreateEncryptor();
&amp;nbsp;
&lt;span class="rem"&gt;// Input file&lt;/span&gt;
FileStream infile = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;);
BinaryReader br = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryReader(infile);
&amp;nbsp;
&lt;span class="rem"&gt;// Output file (encrypted)&lt;/span&gt;
FileStream outfile = File.Create(&lt;span class="str"&gt;"c:\\filenameEnc.bin"&lt;/span&gt;);
CryptoStream encryptor = &lt;span class="kwrd"&gt;new&lt;/span&gt; CryptoStream(outfile, encryptTransf, CryptoStreamMode.Write);
&amp;nbsp;
&lt;span class="rem"&gt;// Now, encrypting&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] b = br.ReadBytes(1000);
&lt;span class="kwrd"&gt;while&lt;/span&gt; (b.Length &amp;gt; 0)
{    
    encryptor.Write(b, 0, b.Length);
    b = br.ReadBytes(1000);
}
&amp;nbsp;
&lt;span class="rem"&gt;// Final&lt;/span&gt;
encryptor.FlushFinalBlock();
encryptor.Close();
br.Close();
&lt;span class="rem"&gt;//----------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;//----------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Now, decryption&lt;/span&gt;
ICryptoTransform decryptTrans = aes.CreateDecryptor();
&amp;nbsp;
&lt;span class="rem"&gt;// Input encrypted file&lt;/span&gt;
infile = File.OpenRead(&lt;span class="str"&gt;"c:\\filenameEnc.bin"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Output, decrypted file&lt;/span&gt;
outfile = File.Create(&lt;span class="str"&gt;"c:\\filenameDec.txt"&lt;/span&gt;);
BinaryWriter bw = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryWriter(outfile);
&amp;nbsp;
CryptoStream decryptor = &lt;span class="kwrd"&gt;new&lt;/span&gt; CryptoStream(infile, decryptTrans, CryptoStreamMode.Read);
&amp;nbsp;
&lt;span class="rem"&gt;// Now, decrypting&lt;/span&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt; bytes = 1000;
b = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[bytes];
&lt;span class="kwrd"&gt;do&lt;/span&gt;
{
    bytes = decryptor.Read(b, 0, b.Length);
    bw.Write(b, 0, bytes);
&amp;nbsp;
} &lt;span class="kwrd"&gt;while&lt;/span&gt; (bytes &amp;gt; 0);
&amp;nbsp;
&lt;span class="rem"&gt;// Final&lt;/span&gt;
decryptor.Close();
bw.Close();
&lt;span class="rem"&gt;//----------------------------------------&lt;/span&gt;
&lt;/pre&gt;

Encrypting using Asymmetric algorithms:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Csp: Crytographic Service Provider&lt;/span&gt;
&lt;span class="rem"&gt;// Create a CspParameters object to store our keys permanently in this machine&lt;/span&gt;
CspParameters persistantCsp = &lt;span class="kwrd"&gt;new&lt;/span&gt; CspParameters();
persistantCsp.KeyContainerName = &lt;span class="str"&gt;"myAsymmetricKey"&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// Create an instance of the RSA algorithm object&lt;/span&gt;
RSACryptoServiceProvider myRSA = &lt;span class="kwrd"&gt;new&lt;/span&gt; RSACryptoServiceProvider(persistantCsp);
&amp;nbsp;
&lt;span class="rem"&gt;// Specify that the private key should be stored in the CSP&lt;/span&gt;
myRSA.PersistKeyInCsp = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// Create a new RSAParameters object with the private key&lt;/span&gt;
RSAParameters privateKey = myRSA.ExportParameters(&lt;span class="kwrd"&gt;true&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing keys&lt;/span&gt;
MessageBox.Show(myRSA.ToXmlString(&lt;span class="kwrd"&gt;true&lt;/span&gt;));
&amp;nbsp;
&lt;span class="rem"&gt;// Now, encrypting some test data&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; data = &lt;span class="str"&gt;"testing data for encryption-12356"&lt;/span&gt;;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] encBytes = Encoding.Unicode.GetBytes(data);
&amp;nbsp;
&lt;span class="rem"&gt;// Encrypt&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] encData = myRSA.Encrypt(encBytes, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Decrypt&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] decBytes = myRSA.Decrypt(encData, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(Encoding.Unicode.GetString(decBytes));
&lt;/pre&gt;

Calculating hashes:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// SHA1 hash provider&lt;/span&gt;
SHA1 myHash = &lt;span class="kwrd"&gt;new&lt;/span&gt; SHA1CryptoServiceProvider();
&amp;nbsp;
&lt;span class="rem"&gt;// Input file&lt;/span&gt;
FileStream file = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// computing the hash&lt;/span&gt;
myHash.ComputeHash(file);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(Convert.ToBase64String(myHash.Hash));
&lt;/pre&gt;

Using keyed hashes:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Test data&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] saltValueBytes = Encoding.ASCII.GetBytes(&lt;span class="str"&gt;"This is my sa1t"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// We're using the PBKDF2 standard for password-based key generation&lt;/span&gt;
Rfc2898DeriveBytes passwordKey = &lt;span class="kwrd"&gt;new&lt;/span&gt; Rfc2898DeriveBytes(&lt;span class="str"&gt;"password"&lt;/span&gt;, saltValueBytes);
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] secretKey = passwordKey.GetBytes(16);
&amp;nbsp;
&lt;span class="rem"&gt;// SHA1 keyed hash&lt;/span&gt;
HMACSHA1 myHash = &lt;span class="kwrd"&gt;new&lt;/span&gt; HMACSHA1(secretKey);
&amp;nbsp;
&lt;span class="rem"&gt;// Input data&lt;/span&gt;
FileStream file = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;);
BinaryReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryReader(file);
&amp;nbsp;
&lt;span class="rem"&gt;// Setting data&lt;/span&gt;
myHash.ComputeHash(reader.ReadBytes((&lt;span class="kwrd"&gt;int&lt;/span&gt;)file.Length));
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(Convert.ToBase64String(myHash.Hash));
&lt;/pre&gt;

Signing data:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;//---------------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Signing provider&lt;/span&gt;
DSACryptoServiceProvider signer = &lt;span class="kwrd"&gt;new&lt;/span&gt; DSACryptoServiceProvider();
&amp;nbsp;
&lt;span class="rem"&gt;// Input data&lt;/span&gt;
FileStream file = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;);
BinaryReader reader = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryReader(file);
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] data = reader.ReadBytes((&lt;span class="kwrd"&gt;int&lt;/span&gt;)file.Length);
&amp;nbsp;
&lt;span class="rem"&gt;// Getting signature&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] signature = signer.SignData(data);
&amp;nbsp;
&lt;span class="rem"&gt;// Exporting our public key to share with someone&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; publicKey = signer.ToXmlString(&lt;span class="kwrd"&gt;false&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(&lt;span class="str"&gt;"Signature: "&lt;/span&gt; + Convert.ToBase64String(signature));
&amp;nbsp;
reader.Close();
&lt;span class="rem"&gt;//---------------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;//---------------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Verifying signature&lt;/span&gt;
DSACryptoServiceProvider verifier = &lt;span class="kwrd"&gt;new&lt;/span&gt; DSACryptoServiceProvider();
&amp;nbsp;
&lt;span class="rem"&gt;// Importing our public key&lt;/span&gt;
verifier.FromXmlString(publicKey);
&amp;nbsp;
&lt;span class="rem"&gt;// Getting original data&lt;/span&gt;
FileStream file2 = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;);
BinaryReader reader2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryReader(file2);
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] data2 = reader2.ReadBytes((&lt;span class="kwrd"&gt;int&lt;/span&gt;)file2.Length);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (verifier.VerifyData(data2, signature))
    MessageBox.Show(&lt;span class="str"&gt;"Signature OK"&lt;/span&gt;);
&lt;span class="kwrd"&gt;else&lt;/span&gt;
    MessageBox.Show(&lt;span class="str"&gt;"Bad Signature"&lt;/span&gt;);
&amp;nbsp;
reader2.Close();
&lt;span class="rem"&gt;//---------------------------------------------&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Other providers:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

Symmetric algorithms:&lt;br&gt;&lt;br&gt;

&lt;em&gt;RijndaelManaged (AES)&lt;br&gt;
RC2&lt;br&gt;
DES&lt;br&gt;
TripleDES&lt;/em&gt;&lt;br&gt;&lt;br&gt;

Asymmetric algorithms:&lt;br&gt;&lt;br&gt;

&lt;em&gt;RSACryptoServiceProvider&lt;br&gt;
DSACryptoServiceProvider&lt;/em&gt;&lt;br&gt;&lt;br&gt;

Hash algorithms:&lt;br&gt;&lt;br&gt;

&lt;em&gt;MD5&lt;br&gt;
RIPEMD160&lt;br&gt;
SHA1&lt;br&gt;
SHA256&lt;br&gt;
SHA384&lt;br&gt;
SHA512&lt;/em&gt;&lt;br&gt;&lt;br&gt;

Keyed hash algorithms:&lt;br&gt;&lt;br&gt;

&lt;em&gt;HMACSHA1&lt;br&gt;
MACTripleDESC&lt;/em&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5108847806198198009?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5108847806198198009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5108847806198198009' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5108847806198198009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5108847806198198009'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/encrypting-and-decrypting-data.html' title='Encrypting and Decrypting Data'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6519964507387915856</id><published>2008-01-27T18:03:00.000-08:00</published><updated>2008-02-09T09:30:57.040-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>ACL's</title><content type='html'>Working with files:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our file security object&lt;/span&gt;
FileSecurity fs = File.GetAccessControl(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;, AccessControlSections.All);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing access rules data&lt;/span&gt;
AuthorizationRuleCollection arc = fs.GetAccessRules(&lt;span class="kwrd"&gt;true&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(NTAccount));
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (FileSystemAccessRule ar &lt;span class="kwrd"&gt;in&lt;/span&gt; arc)
{
    MessageBox.Show(&lt;span class="str"&gt;"Access to: "&lt;/span&gt; + ar.IdentityReference.Value);
    MessageBox.Show(&lt;span class="str"&gt;"Access to: "&lt;/span&gt; + ar.AccessControlType.ToString());
    MessageBox.Show(&lt;span class="str"&gt;"Access to: "&lt;/span&gt; + ar.FileSystemRights.ToString());
}
&amp;nbsp;
&lt;span class="rem"&gt;// Showing audit rules data&lt;/span&gt;
arc = fs.GetAuditRules(&lt;span class="kwrd"&gt;true&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(NTAccount));
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (FileSystemAuditRule ar &lt;span class="kwrd"&gt;in&lt;/span&gt; arc)
{
    MessageBox.Show(&lt;span class="str"&gt;"Audit to: "&lt;/span&gt; + ar.IdentityReference.Value);
    MessageBox.Show(&lt;span class="str"&gt;"Audit to: "&lt;/span&gt; + ar.AuditFlags.ToString());
    MessageBox.Show(&lt;span class="str"&gt;"Audit to: "&lt;/span&gt; + ar.FileSystemRights.ToString());
}
&lt;/pre&gt;

Working with directories:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our file security object&lt;/span&gt;
DirectorySecurity ds = Directory.GetAccessControl(&lt;span class="str"&gt;"c:\\temp"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing access rules data&lt;/span&gt;
AuthorizationRuleCollection arc = ds.GetAccessRules(&lt;span class="kwrd"&gt;true&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(NTAccount));
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (FileSystemAccessRule ar &lt;span class="kwrd"&gt;in&lt;/span&gt; arc)
{
    MessageBox.Show(&lt;span class="str"&gt;"Access to: "&lt;/span&gt; + ar.IdentityReference.Value);
    MessageBox.Show(&lt;span class="str"&gt;"Access to: "&lt;/span&gt; + ar.AccessControlType.ToString());
    MessageBox.Show(&lt;span class="str"&gt;"Access to: "&lt;/span&gt; + ar.FileSystemRights.ToString());
}
&lt;/pre&gt;

Performing changes in file ACL's:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our file security object&lt;/span&gt;
FileSecurity fs = File.GetAccessControl(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;, AccessControlSections.All);
&amp;nbsp;
&lt;span class="rem"&gt;// Add a new rule&lt;/span&gt;
fs.AddAccessRule(&lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemAccessRule(&lt;span class="str"&gt;"Guests"&lt;/span&gt;, FileSystemRights.Read, AccessControlType.Allow));
&amp;nbsp;
&lt;span class="rem"&gt;// Save changes&lt;/span&gt;
File.SetAccessControl(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;, fs);
&lt;/pre&gt;

For directories:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our file security object&lt;/span&gt;
DirectorySecurity ds = Directory.GetAccessControl(&lt;span class="str"&gt;"c:\\temp"&lt;/span&gt;, AccessControlSections.All);
&amp;nbsp;
&lt;span class="rem"&gt;// Add a new rule&lt;/span&gt;
ds.AddAccessRule(&lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemAccessRule(&lt;span class="str"&gt;"Guests"&lt;/span&gt;, FileSystemRights.Read, AccessControlType.Allow));
&amp;nbsp;
&lt;span class="rem"&gt;// Save changes&lt;/span&gt;
Directory.SetAccessControl(&lt;span class="str"&gt;"c:\\temp"&lt;/span&gt;, ds);
&lt;/pre&gt;

Creating directories with initial permissions:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our file security object&lt;/span&gt;
DirectorySecurity ds = &lt;span class="kwrd"&gt;new&lt;/span&gt; DirectorySecurity();
&amp;nbsp;
&lt;span class="rem"&gt;// Setting the rule&lt;/span&gt;
ds.AddAccessRule(&lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemAccessRule(&lt;span class="str"&gt;"Guests"&lt;/span&gt;, FileSystemRights.FullControl, AccessControlType.Allow));
&amp;nbsp;
&lt;span class="rem"&gt;// Creating the directory with our ACL's&lt;/span&gt;
Directory.CreateDirectory(&lt;span class="str"&gt;"c:\\guests"&lt;/span&gt;, ds);
&lt;/pre&gt;

Removing ACL's:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our file security object&lt;/span&gt;
FileSecurity fs = File.GetAccessControl(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;, AccessControlSections.All);
&amp;nbsp;
&lt;span class="rem"&gt;// Add a new rule&lt;/span&gt;
fs.RemoveAccessRuleAll(&lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemAccessRule(&lt;span class="str"&gt;"Guests"&lt;/span&gt;, FileSystemRights.Read, AccessControlType.Allow));
&lt;span class="rem"&gt;//fs.RemoveAccessRule(new FileSystemAccessRule("Guests", FileSystemRights.Read, AccessControlType.Allow));&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Save changes&lt;/span&gt;
File.SetAccessControl(&lt;span class="str"&gt;"c:\\filename.txt"&lt;/span&gt;, fs);
&lt;/pre&gt;

Other Access Rules classes:&lt;br&gt;&lt;br&gt;

&lt;em&gt;EventWaitHandleAccessRule&lt;br&gt;
MutexAccessRule&lt;br&gt;
RegistryAccessRule&lt;br&gt;
SemaphoreAccessRule&lt;/em&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6519964507387915856?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6519964507387915856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6519964507387915856' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6519964507387915856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6519964507387915856'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/acls.html' title='ACL&apos;s'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-975454075635020575</id><published>2008-01-27T14:30:00.000-08:00</published><updated>2008-02-09T09:31:59.216-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>User Permissions</title><content type='html'>After getting the current logged user, we can achieve tasks like ask for user's groups belong to, or use the declarative and imperative permission demand:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Define the security policy in use as Windows security&lt;/span&gt;
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
&amp;nbsp;
&lt;span class="kwrd"&gt;try&lt;/span&gt;
{
    &lt;span class="rem"&gt;// User must belong to Administrators group&lt;/span&gt;
    PrincipalPermission pp = &lt;span class="kwrd"&gt;new&lt;/span&gt; PrincipalPermission(&lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"Administrators"&lt;/span&gt;);
    pp.Demand();
&amp;nbsp;
    &lt;span class="rem"&gt;// User is an administrator&lt;/span&gt;
    MessageBox.Show(&lt;span class="str"&gt;"Only administrators can see this message."&lt;/span&gt;);
}
&lt;span class="kwrd"&gt;catch&lt;/span&gt; (SecurityException)
{
    MessageBox.Show(&lt;span class="str"&gt;"Access denied"&lt;/span&gt;);
}
&lt;span class="kwrd"&gt;catch&lt;/span&gt;(Exception ex)
{
    MessageBox.Show(ex.Message);
}
&lt;/pre&gt;

Using declarative demand:

&lt;pre class="csharpcode"&gt;
[PrincipalPermission(SecurityAction.Demand, Role = &lt;span class="str"&gt;"Administrators"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;void&lt;/span&gt; AdministratorsOnlyMethod()
{
    &lt;span class="rem"&gt;// User is an administrator&lt;/span&gt;
    MessageBox.Show(&lt;span class="str"&gt;"Only administrators can see this message."&lt;/span&gt;);
}
&lt;/pre&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; The &lt;em&gt;PrincipalPermission&lt;/em&gt; only exposes three properties: &lt;em&gt;Authenticated, Name&lt;/em&gt; and &lt;em&gt;Role&lt;/em&gt;.&lt;br&gt;&lt;br&gt;


&lt;strong&gt;WindowsIdentity and WindowsPrincipal classes&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

The &lt;em&gt;WindowsIdentity &lt;/em&gt;class has several methods for getting identities and their properties: &lt;em&gt;GetAnonymous, GetCurrent, Impersonate&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

Properties: &lt;em&gt;AuthenticationType, IsAnonymous, IsAuthenticated, IsGuest, IsSystem, Name ("DOMAIN\Username"), Token&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

The &lt;em&gt;WindowsPrincipal&lt;/em&gt; provides information about groups the user is belong to.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting the current identity and principal representation&lt;/span&gt;
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = &lt;span class="kwrd"&gt;new&lt;/span&gt; WindowsPrincipal(wi);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing some properties&lt;/span&gt;
MessageBox.Show(wi.AuthenticationType);
&amp;nbsp;
MessageBox.Show(wp.IsInRole(WindowsBuiltInRole.Administrator).ToString());
MessageBox.Show(wp.IsInRole(WindowsBuiltInRole.Guest).ToString());
MessageBox.Show(wp.IsInRole(&lt;span class="str"&gt;"Administrators"&lt;/span&gt;).ToString());
&lt;/pre&gt;

If we need authenticate users agaings a custom database, we must implement our custom identity and principal classes from &lt;em&gt;IIdentity&lt;/em&gt; and &lt;em&gt;IPrincipal&lt;/em&gt; interfaces.  Also, we can extend properties and funcionality from classes like &lt;em&gt;WindowsIdentity&lt;/em&gt;, &lt;em&gt;WindowsPrincipal&lt;/em&gt;, &lt;em&gt;GenericIdentity&lt;/em&gt; and &lt;em&gt;GenericPrincipal&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myIdentity : IIdentity
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _name, _password;
&amp;nbsp;
    &lt;span class="rem"&gt;// Custom constructor&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myIdentity(&lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;string&lt;/span&gt; password)
    {
        _name = name;
        _password = password;
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#region&lt;/span&gt; IIdentity Members
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; AuthenticationType
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"custom"&lt;/span&gt;; }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsAuthenticated
    {
        get 
        { 
            &lt;span class="rem"&gt;// Our custom validation, like getting passwords&lt;/span&gt;
            &lt;span class="rem"&gt;// from a local database could be here&lt;/span&gt;
            &lt;span class="kwrd"&gt;return&lt;/span&gt; (_password == _name + &lt;span class="str"&gt;"123"&lt;/span&gt;);
        }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _name; }
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;
}
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myPrincipal: IPrincipal
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; myIdentity _identity;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] _roles;
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myPrincipal(myIdentity identity, &lt;span class="kwrd"&gt;string&lt;/span&gt;[] roles)
    {
        _identity = identity;
        _roles = roles;
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#region&lt;/span&gt; IPrincipal Members
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; IIdentity Identity
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _identity; }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsInRole(&lt;span class="kwrd"&gt;string&lt;/span&gt; role)
    {
        &lt;span class="rem"&gt;// Here, we can search for identity's roles&lt;/span&gt;
        &lt;span class="rem"&gt;// in our custom database&lt;/span&gt;
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; s &lt;span class="kwrd"&gt;in&lt;/span&gt; _roles)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (s.ToLower() == role.ToLower())
                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
        }
&amp;nbsp;  
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;
}
&lt;/pre&gt;

Using our custom identity and principal:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// validate our user&lt;/span&gt;
myIdentity mi = &lt;span class="kwrd"&gt;new&lt;/span&gt; myIdentity(&lt;span class="str"&gt;"john"&lt;/span&gt;, &lt;span class="str"&gt;"john123"&lt;/span&gt;);
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!mi.IsAuthenticated)
{
    MessageBox.Show(&lt;span class="str"&gt;"Invalid username/password"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;return&lt;/span&gt;;
}
&amp;nbsp;
&lt;span class="rem"&gt;// Set some roles&lt;/span&gt;
myPrincipal mp = &lt;span class="kwrd"&gt;new&lt;/span&gt; myPrincipal(mi, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] {&lt;span class="str"&gt;"users"&lt;/span&gt;, &lt;span class="str"&gt;"accounting"&lt;/span&gt;});
&amp;nbsp;
&lt;span class="rem"&gt;// Assign to the thread's current principal&lt;/span&gt;
Thread.CurrentPrincipal = mp;
&amp;nbsp;
&lt;span class="kwrd"&gt;try&lt;/span&gt;
{
    PrincipalPermission pp = &lt;span class="kwrd"&gt;new&lt;/span&gt; PrincipalPermission(&lt;span class="str"&gt;"john"&lt;/span&gt;, &lt;span class="str"&gt;"accounting"&lt;/span&gt;);
    pp.Demand();
&amp;nbsp;
    MessageBox.Show(&lt;span class="str"&gt;"performing some accounting code"&lt;/span&gt;);
}
&lt;span class="kwrd"&gt;catch&lt;/span&gt;(Exception ex)
{
    MessageBox.Show(ex.Message);
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-975454075635020575?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/975454075635020575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=975454075635020575' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/975454075635020575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/975454075635020575'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/user-based-permissions.html' title='User Permissions'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8087945979009058500</id><published>2008-01-26T14:07:00.000-08:00</published><updated>2008-02-09T09:34:28.747-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Code Access Security (CAS)</title><content type='html'>&lt;strong&gt;Evidence&lt;/strong&gt;: represents the origin of code (&lt;em&gt;Application Directory, Hash, Permission Request, Publisher, Site Web, Strong Name, URL, Zone&lt;/em&gt;).&lt;br&gt;&lt;br&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; For configuring the .NET Framework security we use the &lt;em&gt;mscorcfg.msc&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Policy Levels&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;em&gt;Enterprise&lt;/em&gt; (%Systemroot%\Microsoft.NET\Framework\version\Config\enterprise.config)&lt;br&gt;
&lt;em&gt;Machine&lt;/em&gt; (%Systemroot%\Microsoft.NET\Framework\version\Config\security.config)&lt;br&gt;
&lt;em&gt;User&lt;/em&gt; (%UserProfile%\Application Data\Microsoft\CLR Security Config\version\security.config)&lt;br&gt;
&lt;em&gt;AppDomain&lt;/em&gt;&lt;br&gt;&lt;br&gt;

For every &lt;em&gt;Policy Level&lt;/em&gt; we have the &lt;strong&gt;All_Code&lt;/strong&gt; group and several &lt;strong&gt;Permissions Sets&lt;/strong&gt;.  From the &lt;em&gt;All_Code&lt;/em&gt; group, we can get others code groups specific for every &lt;em&gt;Zone&lt;/em&gt; we have (&lt;em&gt;Internet, Intranet, Restricted, Trusted, My_Computer, ...&lt;/em&gt;).  &lt;br&gt;&lt;br&gt;

We can create our custom &lt;em&gt;Code Group&lt;/em&gt; and assign to them our custom &lt;em&gt;Permission Set&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;a href="http://www.developer.com/security/article.php/3483866"&gt;Here one practical sample from developer.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;

Sample:&lt;br&gt;

- Create the strong naming key:  &lt;em&gt;"sn.exe -k mycas.snk"&lt;/em&gt;&lt;br&gt;
- Assign it to our project: &lt;em&gt;Project Properties\Signing&lt;/em&gt; or setting the option &lt;em&gt;[assembly: AssemblyKeyFile(@"..\..\mycas.snk")]&lt;/em&gt; in &lt;em&gt;AssemblyInfo.cs&lt;/em&gt;.&lt;br&gt;
- Create a new &lt;em&gt;Code Group&lt;/em&gt; below the &lt;em&gt;User Policy level&lt;/em&gt;.  For the membership condition, use the &lt;em&gt;Strong Name&lt;/em&gt; and import it from the assembly.&lt;br&gt;
- Create a new Permission set for this group and specify permissions like &lt;em&gt;[File IO, C:\, Read only], [File Dialog, Open only], [User Interface, Unrestricted access] and [Security, Enable Assembly Execution].&lt;/em&gt;&lt;br&gt;&lt;br&gt;

IMPORTANT: For the new created group ensure that you have checked the option: &lt;em&gt;This policy level will only have the permissions from the permission set associated with this code group&lt;/em&gt;&lt;br&gt;&lt;br&gt;

Running the following code will thrown an exception because we dont have write access to &lt;strong&gt;c:\&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        StreamWriter sw = File.CreateText(&lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
        sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
        sw.Close();
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (SecurityException securityEx)
    {
        MessageBox.Show(securityEx.Message, &lt;span class="str"&gt;"Security Exception"&lt;/span&gt;);
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
    {
        MessageBox.Show(ex.Message, &lt;span class="str"&gt;"Exception"&lt;/span&gt;);
    }
}
&lt;/pre&gt;

&lt;strong&gt;Using imperative security check:&lt;/strong&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    FileIOPermission filePermission = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileIOPermission(FileIOPermissionAccess.Write, &lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        filePermission.Demand(); &lt;span class="rem"&gt;// Permission demand&lt;/span&gt;
&amp;nbsp;
        StreamWriter sw = File.CreateText(&lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
        sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
        sw.Close();
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (SecurityException securityEx)
    {
        MessageBox.Show(securityEx.Message, &lt;span class="str"&gt;"Security Exception"&lt;/span&gt;);
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
    {
        MessageBox.Show(ex.Message, &lt;span class="str"&gt;"Exception"&lt;/span&gt;);
    }
}
&lt;/pre&gt;

We can also use the &lt;em&gt;Security Manager&lt;/em&gt; to verify we have permissions before demand it.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    FileIOPermission filePermission = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileIOPermission(FileIOPermissionAccess.Write, &lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (SecurityManager.IsGranted(filePermission))
        {
            filePermission.Demand(); &lt;span class="rem"&gt;// Permission &lt;/span&gt;
&amp;nbsp;
            StreamWriter sw = File.CreateText(&lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
            sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
            sw.Close();
        }
        &lt;span class="kwrd"&gt;else&lt;/span&gt;
            MessageBox.Show(&lt;span class="str"&gt;"You don't have access to c:\\filename.txt"&lt;/span&gt;, &lt;span class="str"&gt;"Access Denied"&lt;/span&gt;);
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (SecurityException securityEx)
    {
        MessageBox.Show(securityEx.Message, &lt;span class="str"&gt;"Security Exception"&lt;/span&gt;);
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
    {
        MessageBox.Show(ex.Message, &lt;span class="str"&gt;"Exception"&lt;/span&gt;);
    }
}
&lt;/pre&gt;

&lt;strong&gt;Using Declarative security check:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

An exception is thrown before the application run the code, so our method is more simple now:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[FileIOPermission(SecurityAction.Demand, Write=&lt;span class="str"&gt;@"C:\filename.txt"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        StreamWriter sw = File.CreateText(&lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
        sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
        sw.Close();
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
    {
        MessageBox.Show(ex.Message, &lt;span class="str"&gt;"Exception"&lt;/span&gt;);
    }
}
&lt;/pre&gt;

Bypass check using &lt;em&gt;Assert&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; button1_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    FileIOPermission filePermission = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileIOPermission(FileIOPermissionAccess.AllAccess, &lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
&amp;nbsp;   
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        filePermission.Assert(); &lt;span class="rem"&gt;// Bypass permission&lt;/span&gt;
&amp;nbsp;
        StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(&lt;span class="str"&gt;@"c:\filename.txt"&lt;/span&gt;);
        sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
        sw.Close();
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
    {
        MessageBox.Show(ex.Message, &lt;span class="str"&gt;"Exception"&lt;/span&gt;);
    }
}
&lt;/pre&gt;

&lt;strong&gt;Assembly Declarations:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

The following declaration checks if we have access to &lt;em&gt;c:\temp\filename.txt&lt;/em&gt;, otherwise an exception is thrown:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[assembly: FileIOPermission(SecurityAction.RequestMinimum, ViewAndModify=&lt;span class="str"&gt;@"c:\temp\filename.txt"&lt;/span&gt;)]&lt;/pre&gt;

If we want to allow only access to specific resources, we should use &lt;em&gt;RequestOptional&lt;/em&gt;.  Example, by using the following declaration, if we try to access other file than &lt;em&gt;c:\temp\filename.txt&lt;/em&gt;, an exception will be thrown.

&lt;pre class="csharpcode"&gt;
[assembly: FileIOPermission(SecurityAction.RequestOptional, ViewAndModify=&lt;span class="str"&gt;@"c:\temp\filename.txt"&lt;/span&gt;)]&lt;/pre&gt;
 
For refuse access to specific resources, we can use &lt;em&gt;RequestRefuse&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[assembly: FileIOPermission(SecurityAction.RequestRefuse, ViewAndModify = @"c:\windows\")]&lt;/pre&gt;

&lt;strong&gt;Permission Requests:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Assert:&lt;/strong&gt; Bypass permission check. Assemblies must have the &lt;em&gt;Assert Any Permission That Has Been Granted&lt;/em&gt; security permission setting.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Demand:&lt;/strong&gt; Instructs the runtime to throw an exception if the caller and all callers higher in the stack lack the specified permission.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Deny:&lt;/strong&gt; Causes the runtime to reduce the method’s access by removing the specified permission.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;InheritanceDemand:&lt;/strong&gt; Instructs the runtime to throw an exception if the assembly inheriting from the class lacks the specified permission.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;LinkDemand:&lt;/strong&gt; Causes the runtime to throw an exception if the immediate caller, but not callers higher in the stack, lack the specified permission.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;PermitOnly:&lt;/strong&gt; Instructs the runtime to reduce the method’s access by removing all permissions except for the specified permission.&lt;br&gt;&lt;br&gt;

References:&lt;br&gt;&lt;br&gt;

&lt;a href="http://www.developer.com/security/article.php/3488861"&gt;Code Access Security with Microsoft .NET Framework, Part 2&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.code-magazine.com/article.aspx?quickid=0405031&amp;page=1"&gt;Managing .NET Code Access Security (CAS) Policy&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.15seconds.com/issue/040121.htm"&gt;Configuring .NET Code Access Security&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.informit.com/guides/content.aspx?g=dotnet&amp;seqNum=420"&gt;Code Access Security / .NET Reference Guide&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.devx.com/vb2themax/Article/19886"&gt;Code Access Security in the .NET Framework&lt;/a&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8087945979009058500?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8087945979009058500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8087945979009058500' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8087945979009058500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8087945979009058500'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/code-access-security-cas.html' title='Code Access Security (CAS)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4198011596757100853</id><published>2008-01-24T17:10:00.000-08:00</published><updated>2008-01-24T17:13:19.298-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How-To write XML "plain" document, without namespaces and header</title><content type='html'>Here the &lt;em&gt;XmlTextWriterFormattedNoDeclaration&lt;/em&gt; class definition:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; XmlTextWriterFormattedNoDeclaration : System.Xml.XmlTextWriter
{
      &lt;span class="kwrd"&gt;public&lt;/span&gt; XmlTextWriterFormattedNoDeclaration(System.IO.TextWriter w) : &lt;span class="kwrd"&gt;base&lt;/span&gt;(w)
      {
            &lt;span class="rem"&gt;//Formatting = System.Xml.Formatting.Indented;&lt;/span&gt;
      }
&amp;nbsp; 
      &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteStartDocument()
      {
            &lt;span class="rem"&gt;// suppress&lt;/span&gt;
      }
}
&lt;/pre&gt;

And here, how we can use it:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Create an instance for namespace class&lt;/span&gt;
XmlSerializerNamespaces ns = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlSerializerNamespaces();
ns.Add(&lt;span class="str"&gt;""&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// now, serialize the object&lt;/span&gt;
XmlSerializer xmlr = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlSerializer(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Docs));
StringWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringWriter();
XmlTextWriter tw = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlTextWriterFormattedNoDeclaration(sw);
&amp;nbsp;
xmlr.Serialize(tw, docs, ns);
&amp;nbsp; 
MessageBox.Show(sw.ToString());
&lt;/pre&gt;

For deserialization we have:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Deserializing the object&lt;/span&gt;
StringReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringReader(sw.ToString());
Docs docs2 = (Docs) xmlr.Deserialize(sr);
&amp;nbsp;
MessageBox.Show(docs2.ToString());
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4198011596757100853?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4198011596757100853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4198011596757100853' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4198011596757100853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4198011596757100853'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/how-to-write-xml-plain-document-without.html' title='How-To write XML &quot;plain&quot; document, without namespaces and header'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4384594612664397894</id><published>2008-01-24T15:52:00.001-08:00</published><updated>2008-02-09T09:36:30.968-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Xml Serialization</title><content type='html'>The Xml serialization is the most compatible and versatile serialization technique. We can set attributes for the class we want to serialize for produccing the output we want.  Here an example:&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Serializing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Building the object instance&lt;/span&gt;
Person p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"Oscar"&lt;/span&gt;, &lt;span class="str"&gt;"L"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; DateTime(1972, 6, 16));
&amp;nbsp;
&lt;span class="rem"&gt;// Now, the Person class includes a List named Friends&lt;/span&gt;
p.Friends.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"John"&lt;/span&gt;, &lt;span class="str"&gt;"T"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; DateTime(1970, 1, 25)));
p.Friends.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"Mary"&lt;/span&gt;, &lt;span class="str"&gt;"Z"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; DateTime(1975, 12, 1)));
&amp;nbsp;
&lt;span class="rem"&gt;// Our target file stream&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;"c:\\filename.xml"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The xml serializer&lt;/span&gt;
XmlSerializer xs = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlSerializer(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Person));
&amp;nbsp;
&lt;span class="rem"&gt;// Serializing the person object&lt;/span&gt;
xs.Serialize(fs, p);
&amp;nbsp;
fs.Close();  &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Deserializing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our source file stream&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.xml"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The xml serializer&lt;/span&gt;
XmlSerializer xs = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlSerializer(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Person));
&amp;nbsp;
&lt;span class="rem"&gt;// Deserializing the object&lt;/span&gt;
Person p = (Person)xs.Deserialize(fs);
&amp;nbsp;
fs.Close();  &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(p.FirstName + &lt;span class="str"&gt;" "&lt;/span&gt; + p.Age.ToString());
MessageBox.Show(&lt;span class="str"&gt;"Number of friends: "&lt;/span&gt; + p.Friends.Count.ToString());
&lt;/pre&gt;

And here the &lt;em&gt;Person&lt;/em&gt; class definition:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[XmlRoot(ElementName=&lt;span class="str"&gt;"thisPerson"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person
{
    [XmlElement(ElementName=&lt;span class="str"&gt;"Name"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName;
&amp;nbsp;
    [XmlAttribute]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime BirthDay;
&amp;nbsp;
    [XmlIgnore]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Age;
&amp;nbsp;
    [XmlArray(&lt;span class="str"&gt;"myFriends"&lt;/span&gt;)]
    [XmlArrayItem(&lt;span class="str"&gt;"myFriend"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; People Friends = &lt;span class="kwrd"&gt;new&lt;/span&gt; People();
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person(&lt;span class="kwrd"&gt;string&lt;/span&gt; _firstName, &lt;span class="kwrd"&gt;string&lt;/span&gt; _lastName, DateTime _birthDay)
    {
        FirstName = _firstName;
        LastName = _lastName;
        BirthDay = _birthDay;
&amp;nbsp;
        Age = DateTime.Now.Year - BirthDay.Year - 1;
    }
}
&amp;nbsp;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; People : List&amp;lt;Person&amp;gt;
{
}
&lt;/pre&gt;

Notice how I named the root node as &lt;em&gt;'thisPerson'&lt;/em&gt; and the element &lt;em&gt;FirstName&lt;/em&gt; as &lt;em&gt;'Name'&lt;/em&gt;.  I also set the &lt;em&gt;BirthDay&lt;/em&gt; for serializing as an &lt;em&gt;XmlAttribute&lt;/em&gt; instead of an &lt;em&gt;XmlElement&lt;/em&gt;.  And I set the &lt;em&gt;Age&lt;/em&gt; for ignoring it (XmlIgnore attribute) so it will not included into the output.&lt;br&gt;&lt;br&gt;

For the list named &lt;em&gt;Friends&lt;/em&gt;, I apply the &lt;em&gt;XmlArray&lt;/em&gt; attribute to named it as &lt;em&gt;'myFriends'&lt;/em&gt; and every item in the collection as &lt;em&gt;'myFriend'&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

This will produce the following output:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;thisPerson&lt;/span&gt; &lt;span class="attr"&gt;xmlns:xsi&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:xsd&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.w3.org/2001/XMLSchema"&lt;/span&gt; &lt;span class="attr"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;="1972-06-16T00:00:00"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Oscar&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;L&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt; &lt;span class="attr"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;="1970-01-25T00:00:00"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;John&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;T&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt; &lt;span class="attr"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;="1975-12-01T00:00:00"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Mary&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Z&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;thisPerson&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

If we want to control errors, we need to handle some events:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Event handlers&lt;/span&gt;
xs.UnknownAttribute += &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlAttributeEventHandler(xs_UnknownAttribute);
xs.UnknownElement += &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlElementEventHandler(xs_UnknownElement);
xs.UnknownNode += &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlNodeEventHandler(xs_UnknownNode);
xs.UnreferencedObject += &lt;span class="kwrd"&gt;new&lt;/span&gt; UnreferencedObjectEventHandler(xs_UnreferencedObject);
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; xs_UnreferencedObject(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, UnreferencedObjectEventArgs e)
{
    &lt;span class="rem"&gt;// something happen&lt;/span&gt;
}
&amp;nbsp;
&lt;span class="kwrd"&gt;void&lt;/span&gt; xs_UnknownNode(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, XmlNodeEventArgs e)
{
    &lt;span class="rem"&gt;// something happen&lt;/span&gt;
}
&amp;nbsp;
&lt;span class="kwrd"&gt;void&lt;/span&gt; xs_UnknownElement(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, XmlElementEventArgs e)
{
    &lt;span class="rem"&gt;// something happen&lt;/span&gt;
}
&amp;nbsp;
&lt;span class="kwrd"&gt;void&lt;/span&gt; xs_UnknownAttribute(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, XmlAttributeEventArgs e)
{
    &lt;span class="rem"&gt;// something happen&lt;/span&gt;
}
&lt;/pre&gt;

&lt;strong&gt;Implementing the &lt;em&gt;IXmlSerializable&lt;/em&gt;:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

If we want more control over serialization, we need to implement the interface &lt;em&gt;IXmlSerializable&lt;/em&gt; as bellow:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[XmlRoot(ElementName = &lt;span class="str"&gt;"thisPerson"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person : IXmlSerializable
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime BirthDay;
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Age;
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; People Friends = &lt;span class="kwrd"&gt;new&lt;/span&gt; People();
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person(&lt;span class="kwrd"&gt;string&lt;/span&gt; _firstName, &lt;span class="kwrd"&gt;string&lt;/span&gt; _lastName, DateTime _birthDay)
    {
        FirstName = _firstName;
        LastName = _lastName;
        BirthDay = _birthDay;
&amp;nbsp;
        Age = DateTime.Now.Year - BirthDay.Year - 1;
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#region&lt;/span&gt; IXmlSerializable Members
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; System.Xml.Schema.XmlSchema GetSchema()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;null&lt;/span&gt;);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ReadXml(System.Xml.XmlReader reader)
    {
        reader.MoveToContent();
&amp;nbsp;
        BirthDay = DateTime.Parse(reader.GetAttribute(&lt;span class="str"&gt;"BirthDay"&lt;/span&gt;));
&amp;nbsp;
        FirstName = reader.ReadElementString();
        LastName = reader.ReadElementString();
        Age = &lt;span class="kwrd"&gt;int&lt;/span&gt;.Parse(reader.ReadElementString());
&amp;nbsp;
        &lt;span class="rem"&gt;// Reading friends collection&lt;/span&gt;
        Friends.Clear();
&amp;nbsp;
        &lt;span class="kwrd"&gt;int&lt;/span&gt; depth = reader.Depth;  &lt;span class="rem"&gt;// actual depth&lt;/span&gt;
        &lt;span class="kwrd"&gt;bool&lt;/span&gt; read = reader.Read(); &lt;span class="rem"&gt;// next read&lt;/span&gt;
        &lt;span class="kwrd"&gt;while&lt;/span&gt; ((read) &amp;amp;&amp;amp; (reader.Depth &amp;gt; depth))
        {
            reader.MoveToContent(); 
&amp;nbsp;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (reader.IsStartElement())
            {
                Person p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Person();
                p.ReadXml(reader);
                Friends.Add(p);
            }
&amp;nbsp;
            read = reader.Read();
        }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteAttributeString(&lt;span class="str"&gt;"BirthDay"&lt;/span&gt;, BirthDay.ToString());
        writer.WriteElementString(&lt;span class="str"&gt;"Name"&lt;/span&gt;, FirstName);
        writer.WriteElementString(&lt;span class="str"&gt;"LastName"&lt;/span&gt;, LastName);
        writer.WriteElementString(&lt;span class="str"&gt;"Age"&lt;/span&gt;, Age.ToString());
&amp;nbsp;
        writer.WriteStartElement(&lt;span class="str"&gt;"myFriends"&lt;/span&gt;);
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Person p &lt;span class="kwrd"&gt;in&lt;/span&gt; Friends)
        {
            writer.WriteStartElement(&lt;span class="str"&gt;"myFriend"&lt;/span&gt;);
            p.WriteXml(writer);
            writer.WriteEndElement();
        }
        writer.WriteEndElement();
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;
}    
&amp;nbsp;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; People : List&amp;lt;Person&amp;gt;
{
}
&lt;/pre&gt;

And here the output it produces:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;thisPerson&lt;/span&gt; &lt;span class="attr"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;="6/16/1972 12:00:00 AM"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Oscar&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;L&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Age&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;35&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Age&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt; &lt;span class="attr"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;="1/25/1970 12:00:00 AM"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;John&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;T&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Age&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;37&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Age&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt; &lt;span class="attr"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;="12/1/1975 12:00:00 AM"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Mary&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Z&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Age&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;32&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Age&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myFriend&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myFriends&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;thisPerson&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4384594612664397894?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4384594612664397894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4384594612664397894' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4384594612664397894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4384594612664397894'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/xml-serialization.html' title='Xml Serialization'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5609676030949876060</id><published>2008-01-24T08:21:00.000-08:00</published><updated>2008-02-09T09:38:06.753-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Binary and Soap serialization</title><content type='html'>We can serialize objects as a binary representation of them, by using the BinaryFormatter class, like this:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Some objects to serialize&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; str = &lt;span class="str"&gt;"test line"&lt;/span&gt;;
DateTime dt = DateTime.Now;
&amp;nbsp;
&lt;span class="rem"&gt;// Our target file stream&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;"c:\\filename.dat"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The binary formatter&lt;/span&gt;
BinaryFormatter bf = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryFormatter();
&amp;nbsp;
&lt;span class="rem"&gt;// Serializing multiple objects&lt;/span&gt;
bf.Serialize(fs, str);
bf.Serialize(fs, dt);
&amp;nbsp;
fs.Close(); &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Deserializing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our source file stream&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.dat"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The binary formatter&lt;/span&gt;
BinaryFormatter bf = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryFormatter();
&amp;nbsp;
&lt;span class="rem"&gt;// Deserializing objects&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; str = (&lt;span class="kwrd"&gt;string&lt;/span&gt;)bf.Deserialize(fs);
DateTime dt = (DateTime)bf.Deserialize(fs);
&amp;nbsp;
fs.Close();  &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(str);
MessageBox.Show(dt.ToString());
&lt;/pre&gt;

We can set preferences for serializing objects by using &lt;em&gt;Serialize Attributes&lt;/em&gt;. Also, if we need to perform some task after deserializing was performed, we need to implement the &lt;em&gt;IDeserializationCallback&lt;/em&gt; interface. &lt;br&gt;&lt;br&gt;

Here an example using a person class that will not serialize the &lt;em&gt;Age&lt;/em&gt; property, cause it is a calculated property.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[Serializable]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person : IDeserializationCallback
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName;
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime BirthDay;
&amp;nbsp;
    [NonSerialized]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Age;
&amp;nbsp;
    [OptionalField]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Alias;
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person(&lt;span class="kwrd"&gt;string&lt;/span&gt; _firstName, &lt;span class="kwrd"&gt;string&lt;/span&gt; _lastName, DateTime _birthDay)
    {
        FirstName = _firstName;
        LastName = _lastName;
        BirthDay = _birthDay;
&amp;nbsp;
        Age = DateTime.Now.Year - BirthDay.Year - 1;
&amp;nbsp;
        Alias = &lt;span class="str"&gt;""&lt;/span&gt;;
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#region&lt;/span&gt; IDeserializationCallback Members
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnDeserialization(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender)
    {
        Alias = &lt;span class="str"&gt;""&lt;/span&gt;;
        Age = DateTime.Now.Year - BirthDay.Year - 1;
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;
}
&lt;/pre&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; The &lt;em&gt;OptionalField&lt;/em&gt; attribute has the property &lt;em&gt;VersionAdded&lt;/em&gt;. This is reserved but we can set this with the correct version for our object, starting from 2. Example: &lt;em&gt;[OptionalField(VersionAdded=2)]&lt;/em&gt;, &lt;em&gt;[OptionalField(VersionAdded=3)]&lt;/em&gt;, and so on.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Serializing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Building the object instance&lt;/span&gt;
Person p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"Oscar"&lt;/span&gt;, &lt;span class="str"&gt;"L"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; DateTime(1972, 6, 16));
&amp;nbsp;
&lt;span class="rem"&gt;// Our target file stream&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;"c:\\filename.dat"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The binary formatter&lt;/span&gt;
BinaryFormatter bf = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryFormatter();
&amp;nbsp;
&lt;span class="rem"&gt;// Serializing the person object&lt;/span&gt;
bf.Serialize(fs, p);
&amp;nbsp;
fs.Close(); &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Deserializing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our source file stream&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.dat"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The binary formatter&lt;/span&gt;
BinaryFormatter bf = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryFormatter();
&amp;nbsp;
&lt;span class="rem"&gt;// Deserializing the object&lt;/span&gt;
Person p = (Person)bf.Deserialize(fs);
&amp;nbsp;
fs.Close();  &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(p.FirstName + &lt;span class="str"&gt;" "&lt;/span&gt; + p.Age.ToString());
&lt;/pre&gt;

The code above will invoke the &lt;em&gt;Person.OnDeserialization&lt;/em&gt; callback, so we can perform some tasks after deserialization was performed, such as, recalculate fields.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;The &lt;em&gt;SoapFormatter&lt;/em&gt; class&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

The &lt;em&gt;SoapFormatter&lt;/em&gt; class works in the same way as the &lt;em&gt;BinaryFormatter&lt;/em&gt;, except that it produces an XML Soap output, so it could be used to transport objects across the network boundaries (over Internet).&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Building the object instance&lt;/span&gt;
Person p = &lt;span class="kwrd"&gt;new&lt;/span&gt; Person(&lt;span class="str"&gt;"Oscar"&lt;/span&gt;, &lt;span class="str"&gt;"L"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; DateTime(1972, 6, 16));
&amp;nbsp;
&lt;span class="rem"&gt;// Our target file stream&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;"c:\\filename.soap"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The soap formatter&lt;/span&gt;
SoapFormatter sf = &lt;span class="kwrd"&gt;new&lt;/span&gt; SoapFormatter();
&amp;nbsp;
&lt;span class="rem"&gt;// Serializing the person object&lt;/span&gt;
sf.Serialize(fs, p);
&amp;nbsp;
fs.Close(); &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&lt;/pre&gt;

Here the output it produces:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;SOAP-ENV:Envelope&lt;/span&gt; &lt;span class="attr"&gt;xmlns:xsi&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:xsd&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.w3.org/2001/XMLSchema"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:SOAP-ENC&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.xmlsoap.org/soap/encoding/"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:SOAP-ENV&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.xmlsoap.org/soap/envelope/"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:clr&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/soap/encoding/clr/1.0"&lt;/span&gt; &lt;span class="attr"&gt;SOAP-ENV:encodingStyle&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.xmlsoap.org/soap/encoding/"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;SOAP-ENV:Body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;a1:Person&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="ref-1"&lt;/span&gt; &lt;span class="attr"&gt;xmlns:a1&lt;/span&gt;&lt;span class="kwrd"&gt;="http://schemas.microsoft.com/clr/nsassem/WindowsFormsApplication6/WindowsFormsApplication6%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;FirstName&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="ref-3"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Oscar&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;FirstName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="ref-4"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;L&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;LastName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;1972-06-16T00:00:00.0000000-05:00&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;BirthDay&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Alias&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="ref-5"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Alias&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;a1:Person&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;SOAP-ENV:Body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;SOAP-ENV:Envelope&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

And here, how we can read back the object:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our source file stream&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;"c:\\filename.soap"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// The soap formatter&lt;/span&gt;
SoapFormatter sf = &lt;span class="kwrd"&gt;new&lt;/span&gt; SoapFormatter();
&amp;nbsp;
&lt;span class="rem"&gt;// Deserializing the object&lt;/span&gt;
Person p = (Person)sf.Deserialize(fs);
&amp;nbsp;
fs.Close();  &lt;span class="rem"&gt;// Don't forget to close the file stream&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Showing results&lt;/span&gt;
MessageBox.Show(p.FirstName + &lt;span class="str"&gt;" "&lt;/span&gt; + p.Age.ToString());
&lt;/pre&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; For using the &lt;em&gt;SoapFormatter&lt;/em&gt;, you need to add the reference to the &lt;em&gt;System.Runtime.Serialization.Formatters.Soap&lt;/em&gt; library.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Implementing a custom serialization:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

If we want to implement our custom serialization, we need to implement the &lt;em&gt;ISerializable&lt;/em&gt; interface and write data when the &lt;em&gt;GetObjectData&lt;/em&gt; is called and implement a new constructor conforms with the &lt;em&gt;ISerializable&lt;/em&gt; specification, like this:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// New class declaration&lt;/span&gt;
&amp;nbsp;
[Serializable]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person : IDeserializationCallback, ISerializable
{
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// New constructor&lt;/span&gt;
&lt;span class="kwrd"&gt;protected&lt;/span&gt; Person(SerializationInfo info, StreamingContext context)
{
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.FirstName = info.GetString(&lt;span class="str"&gt;"FirstName"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.LastName = info.GetString(&lt;span class="str"&gt;"LastName"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.BirthDay = info.GetDateTime(&lt;span class="str"&gt;"BirthDay"&lt;/span&gt;);
&amp;nbsp;
    &lt;span class="rem"&gt;// Custom and calculated methods can be processed here    &lt;/span&gt;
    &lt;span class="kwrd"&gt;string&lt;/span&gt; another = info.GetString(&lt;span class="str"&gt;"another"&lt;/span&gt;);
}
&amp;nbsp;
&lt;span class="rem"&gt;// Implementing the GetObjectData method&lt;/span&gt;
&amp;nbsp;
&lt;span class="preproc"&gt;#region&lt;/span&gt; ISerializable Members
&amp;nbsp;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue(&lt;span class="str"&gt;"FirstName"&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;.FirstName);
    info.AddValue(&lt;span class="str"&gt;"LastName"&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;.LastName);
    info.AddValue(&lt;span class="str"&gt;"BirthDay"&lt;/span&gt;, &lt;span class="kwrd"&gt;this&lt;/span&gt;.BirthDay);
&amp;nbsp;
    &lt;span class="rem"&gt;// Custom and other values can be writed here&lt;/span&gt;
    info.AddValue(&lt;span class="str"&gt;"another"&lt;/span&gt;, &lt;span class="str"&gt;"another value"&lt;/span&gt;);
}
&amp;nbsp;
&lt;span class="preproc"&gt;#endregion&lt;/span&gt;
&amp;nbsp;
...
&amp;nbsp;
} // End of class
&lt;/pre&gt;

Another way for controlling our serialization, can be achieve by using custom methods with serialization attributes (they transform the method in a callback that serialization will call):&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[Serializable]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person : IDeserializationCallback, ISerializable
{
&amp;nbsp;
...
&amp;nbsp;
[OnSerializing()]
&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnSerializingMethod(StreamingContext context)
{
    &lt;span class="rem"&gt;// During serialization&lt;/span&gt;
}
&amp;nbsp;
[OnSerialized()]
&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnSerializedMethod(StreamingContext context)
{
    &lt;span class="rem"&gt;// After serialization&lt;/span&gt;
}
&amp;nbsp;
[OnDeserializing()]
&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnDeserializingMethod(StreamingContext context)
{
    &lt;span class="rem"&gt;// During deserialization&lt;/span&gt;
}
&amp;nbsp;
[OnDeserialized()]
&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnDeserializedMethod(StreamingContext context)
{
    &lt;span class="rem"&gt;// After deserialization&lt;/span&gt;
}
&amp;nbsp;
...
&amp;nbsp;
} // End of class
&lt;/pre&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; The &lt;em&gt;StreamingContext&lt;/em&gt; object can be used to pass some important information to serialization methods (&lt;em&gt;StreamingContext.Context&lt;/em&gt; as object) and can be used to get information about the destination (&lt;em&gt;StreamingContext.State&lt;/em&gt; as &lt;em&gt;StreamingContextStates&lt;/em&gt; enumeration).&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// The binary formatter&lt;/span&gt;
StreamingContext sc = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamingContext(myCustomObject);
BinaryFormatter bf = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryFormatter(&lt;span class="kwrd"&gt;null&lt;/span&gt;, sc);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5609676030949876060?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5609676030949876060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5609676030949876060' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5609676030949876060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5609676030949876060'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/binary-and-soap-serialization.html' title='Binary and Soap serialization'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2591383254949693993</id><published>2008-01-23T16:07:00.000-08:00</published><updated>2008-01-23T16:29:32.341-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Working with IsolatedStorage class</title><content type='html'>Creating a file in our isolated store:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Create our isolated store with Machine/Assembly scope&lt;/span&gt;
&lt;span class="rem"&gt;// Also, we can create one with User/Assembly scope and others.&lt;/span&gt;
IsolatedStorageFile isf = IsolatedStorageFile.GetMachineStoreForAssembly();
&amp;nbsp;
&lt;span class="rem"&gt;// Open our stream for writing to it&lt;/span&gt;
IsolatedStorageFileStream isfs = &lt;span class="kwrd"&gt;new&lt;/span&gt; IsolatedStorageFileStream(&lt;span class="str"&gt;"filename.txt"&lt;/span&gt;, FileMode.Create, isf);
&amp;nbsp;
&lt;span class="rem"&gt;// Using StreamWriter to write&lt;/span&gt;
StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(isfs);
sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
&amp;nbsp;
sw.Flush();
sw.Close(); &lt;span class="rem"&gt;// Close the stream&lt;/span&gt;
&amp;nbsp;
isf.Close();
&lt;/pre&gt;

The isolated store will be created on &lt;em&gt;C:\Documents and Settings\All Users\Application Data\IsolatedStorage\..\..\..\AssemFiles&lt;/em&gt;.

Reading files from our isolated store:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Create our isolated store with Machine/Assembly scope&lt;/span&gt;
IsolatedStorageFile isf = IsolatedStorageFile.GetMachineStoreForAssembly();
&amp;nbsp;
&lt;span class="rem"&gt;// Open our stream for reading from it&lt;/span&gt;
IsolatedStorageFileStream isfs = &lt;span class="kwrd"&gt;new&lt;/span&gt; IsolatedStorageFileStream(&lt;span class="str"&gt;"filename.txt"&lt;/span&gt;, FileMode.Open, isf);
&amp;nbsp;
&lt;span class="rem"&gt;// Using StreamReader to read&lt;/span&gt;
StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(isfs);
MessageBox.Show(sr.ReadToEnd());
&amp;nbsp;
sr.Close(); &lt;span class="rem"&gt;// Close the stream&lt;/span&gt;
&amp;nbsp;
isf.Close();
&lt;/pre&gt;

Using directories:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Create our isolated store with Machine/Assembly scope&lt;/span&gt;
IsolatedStorageFile isf = IsolatedStorageFile.GetMachineStoreForAssembly();
&amp;nbsp;
&lt;span class="rem"&gt;// Create one directory&lt;/span&gt;
isf.CreateDirectory(&lt;span class="str"&gt;"Temp"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Open our stream for writing to it&lt;/span&gt;
IsolatedStorageFileStream isfs = &lt;span class="kwrd"&gt;new&lt;/span&gt; IsolatedStorageFileStream(&lt;span class="str"&gt;@"Temp\filename.txt"&lt;/span&gt;, FileMode.Create, isf);
&amp;nbsp;
&lt;span class="rem"&gt;// Using StreamWriter to write&lt;/span&gt;
StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(isfs);
sw.WriteLine(&lt;span class="str"&gt;"another line"&lt;/span&gt;);
&amp;nbsp;
sw.Flush();
sw.Close();  &lt;span class="rem"&gt;// Close the stream&lt;/span&gt;
&amp;nbsp;
isf.Close();
&lt;/pre&gt;

Also, we can remove our isolated store:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Create our IsolatedStorage with Machine/Assembly scope&lt;/span&gt;
IsolatedStorageFile isf = IsolatedStorageFile.GetMachineStoreForAssembly();
&amp;nbsp;
&lt;span class="rem"&gt;// Removing our isolated store&lt;/span&gt;
isf.Remove();
&lt;/pre&gt;

Other useful methods:

&lt;em&gt;GetFileNames
GetDirectoryNames
DeleteDirectory
DeleteFile&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2591383254949693993?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2591383254949693993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2591383254949693993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2591383254949693993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2591383254949693993'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/working-with-isolatedstorage-class.html' title='Working with IsolatedStorage class'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-3863536083176439620</id><published>2008-01-23T15:48:00.000-08:00</published><updated>2008-02-09T09:39:11.257-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Streams 2</title><content type='html'>There are other useful stream and reader/writer classes.&lt;br&gt;&lt;br&gt;

For working with strings, we can use &lt;em&gt;StringReader&lt;/em&gt; and &lt;em&gt;StringWriter&lt;/em&gt;. Also, remember the &lt;em&gt;StringBuilder&lt;/em&gt; class, but the last one isn't an stream.&lt;br&gt;&lt;br&gt;

&lt;em&gt;TextReader&lt;/em&gt; and &lt;em&gt;TextWriter&lt;/em&gt; are abstract base class that &lt;em&gt;StreamReader&lt;/em&gt;, &lt;em&gt;StreamWriter&lt;/em&gt;, &lt;em&gt;StringReader&lt;/em&gt;, and &lt;em&gt;StringWriter&lt;/em&gt; derive from.&lt;br&gt;&lt;br&gt;

For binary tasks, we can use &lt;em&gt;BinaryReader&lt;/em&gt; and &lt;em&gt;BinaryWriter&lt;/em&gt;.  Here another approach for reading compressed binary files:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the stream we want to decompress&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;@"c:\temp\filename.zip"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creates the GZipStream&lt;/span&gt;
GZipStream gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(fs, CompressionMode.Decompress);
&amp;nbsp;
&lt;span class="rem"&gt;// We want to read binary content into one memory stream&lt;/span&gt;
&lt;span class="rem"&gt;// This could be also a FileStream object&lt;/span&gt;
MemoryStream ms = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
&amp;nbsp;
&lt;span class="rem"&gt;// We use the binary reader for improve the performance&lt;/span&gt;
BinaryReader br = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryReader(gzip);
&amp;nbsp;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] b = br.ReadBytes(1000);
&lt;span class="kwrd"&gt;while&lt;/span&gt; (b.Length &amp;gt; 0)
{
    ms.Write(b, 0, b.Length);
    b = br.ReadBytes(1000);
}
&amp;nbsp;
&lt;span class="rem"&gt;// Show read content's length&lt;/span&gt;
MessageBox.Show(ms.Length.ToString());
ms.Close(); &lt;span class="rem"&gt;// Close our target stream&lt;/span&gt;
&amp;nbsp;
br.Close(); &lt;span class="rem"&gt;// This also closes the GZipStream and the FileStream (the underlying stream)*/&lt;/span&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3863536083176439620?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3863536083176439620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3863536083176439620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3863536083176439620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3863536083176439620'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/streams-2.html' title='Streams 2'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8087183404482794607</id><published>2008-01-23T08:16:00.000-08:00</published><updated>2008-02-09T09:40:50.272-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Streams</title><content type='html'>Some interesting properties and methods for the &lt;em&gt;Stream&lt;/em&gt; class:&lt;br&gt;&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Length:&lt;/strong&gt; Gets the length (in bytes) of the stream.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Position:&lt;/strong&gt; Gets or sets the current position in the stream for reading and writing operations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seek():&lt;/strong&gt; Sets the position within the stream.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Flush():&lt;/strong&gt; Clears any buffers within the stream and forces changes to be written to the underlying system or device. Some streams have the &lt;em&gt;AutoFlush&lt;/em&gt; property for flushing automatically any change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Close():&lt;/strong&gt; Closes the stream and releases any resources associated with it.  &lt;em&gt;!!! Remember always close the stream !!!&lt;/em&gt; &lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Read():&lt;/strong&gt; Performs a sequential read of a specified number of bytes from the current position and updates the position to the end of the
read upon completion of the operation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ReadByte():&lt;/strong&gt; Performs the read of a single byte and updates the position by moving it by one. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Write():&lt;/strong&gt; Writes information to the stream as a number of bytes and updates the current position to reflect the new write position.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WriteByte():&lt;/strong&gt; Writes a single byte to the stream and updates the position. &lt;/li&gt;
&lt;/ul&gt;

There are a lot of streams, some of them:&lt;br&gt;&lt;br&gt;

&lt;em&gt;FileStream&lt;br&gt;
MemoryStream&lt;br&gt;
CryptoStream&lt;br&gt;
NetworkStream&lt;br&gt;
GZipStream&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;The File class&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

The &lt;em&gt;File&lt;/em&gt; class provides methods for easy writing and reading operations.&lt;br&gt;&lt;br&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Copy():&lt;/strong&gt; Copies a file to a new file. &lt;em&gt;!!! The new file must not exist or an event will be thrown. !!!&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Move():&lt;/strong&gt; Moves a file from one place to another.  &lt;em&gt;!!! The target file must not exist or an event will be thrown. !!!&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delete():&lt;/strong&gt; Deletes a file. &lt;em&gt;!!! None exception is throw if file doesn't exists !!!&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exists():&lt;/strong&gt; Returns true if a file exists.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;AppendText():&lt;/strong&gt; Opens a file (or creates a new file if one does not exist) and returns a &lt;em&gt;StreamWriter&lt;/em&gt; that is prepared to allow text to be appended to the file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CreateText():&lt;/strong&gt; Creates or opens a file and returns a &lt;em&gt;StreamWriter&lt;/em&gt; object that is ready to have text written into it.
&lt;li&gt;&lt;strong&gt;OpenText():&lt;/strong&gt; Opens an existing file and returns a &lt;em&gt;StreamReader &lt;/em&gt;object.
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Open():&lt;/strong&gt; Opens an existing file and returns a &lt;em&gt;FileStream&lt;/em&gt; object.  We can specify the file mode and the file access type.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenRead():&lt;/strong&gt; Opens an existing file and returns a read-only &lt;em&gt;FileStream&lt;/em&gt; object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenWrite():&lt;/strong&gt; Opens an existing file for writing and returns a &lt;em&gt;FileStream&lt;/em&gt; object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create():&lt;/strong&gt; Creates a new file and returns a FileStream object.&lt;/li&gt;
&amp;nbsp;
Atomic operations:
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;ReadAllBytes():&lt;/strong&gt; Opens a file, reads the contents of it into a byte array, and closes the file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ReadAllLines():&lt;/strong&gt; Opens a file, reads the contents of it into an array of strings (one per line), and closes the file.&lt;/lid&gt;
&lt;li&gt;&lt;strong&gt;ReadAllText():&lt;/strong&gt; Opens a file, reads the contents of it into a string, and closes the file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WriteAllBytes():&lt;/strong&gt; Opens a file, writes the contents of a byte array into it (overwriting any existing data), and closes the file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WriteAllLines():&lt;/strong&gt; Opens a file, writes the contents of a string array into it (overwriting any existing data), and closes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WriteAllText():&lt;/strong&gt; Opens a file, writes the contents of a string into it (overwriting any existing data), and closes the file.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Reading some bytes&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;"c:\\temp\\filename.txt"&lt;/span&gt;);
&lt;span class="kwrd"&gt;int&lt;/span&gt; b = fs.ReadByte();
fs.Close();
&amp;nbsp;
MessageBox.Show(b.ToString());
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Reading using the StreamReader&lt;/span&gt;
StreamReader sr = File.OpenText(&lt;span class="str"&gt;"c:\\temp\\filename.txt"&lt;/span&gt;);
&amp;nbsp;
MessageBox.Show(sr.ReadToEnd());
&amp;nbsp;
sr.Close(); &lt;span class="rem"&gt;// Dont forget to close the stream&lt;/span&gt;
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Reading all text at once (The easy way!!!)&lt;/span&gt;
MessageBox.Show(File.ReadAllText(&lt;span class="str"&gt;"c:\\temp\\filename.txt"&lt;/span&gt;));
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Reading all lines at once&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt;[] lines = File.ReadAllLines(&lt;span class="str"&gt;"c:\\temp\\filename.txt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt; s &lt;span class="kwrd"&gt;in&lt;/span&gt; lines)
    MessageBox.Show(s);
&lt;/pre&gt;

The &lt;em&gt;FileAccess&lt;/em&gt; enumeration:&lt;br&gt;&lt;br&gt;

&lt;em&gt;Read&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Write&lt;/em&gt;&lt;br&gt;
&lt;em&gt;ReadWrite&lt;/em&gt;&lt;br&gt;&lt;br&gt;

The &lt;em&gt;FileMode&lt;/em&gt; enumeration:&lt;br&gt;&lt;br&gt;

&lt;em&gt;Append&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Create&lt;/em&gt;&lt;br&gt;
&lt;em&gt;CreateNew&lt;/em&gt;:  An exception is thrown if file exists.&lt;br&gt;
&lt;em&gt;Open&lt;/em&gt;: An exception is thrown if file does not exist.&lt;br&gt;
&lt;em&gt;OpenOrCreate&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Truncate&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; The &lt;em&gt;FileStream&lt;/em&gt; also has the &lt;em&gt;Lock&lt;/em&gt; and &lt;em&gt;Unlock&lt;/em&gt; methods to prevent other process from changing all or part of the file.&lt;br&gt;&lt;br&gt;

The &lt;em&gt;StreamReader&lt;/em&gt; and &lt;em&gt;StreamWriter&lt;/em&gt; are classes for easy writing and reading operations with streams.  We can use the property &lt;em&gt;AutoFlush&lt;/em&gt; for automatically flushing the content to the stream.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Writing with StreamWriter&lt;/span&gt;
StreamWriter sw = File.CreateText(&lt;span class="str"&gt;@"c:\temp\filename2.txt"&lt;/span&gt;);
sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
sw.Flush(); &lt;span class="rem"&gt;// Or set sw.AutoFlush = true; to avoid calling this method&lt;/span&gt;
sw.Close(); &lt;span class="rem"&gt;// Dont forget to close the stream &lt;/span&gt;
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Reading with StreamReader&lt;/span&gt;
StreamReader sr = File.OpenText(&lt;span class="str"&gt;@"c:\temp\filename2.txt"&lt;/span&gt;);
&amp;nbsp;
MessageBox.Show(sr.ReadLine());
&amp;nbsp;
sr.Close(); &lt;span class="rem"&gt;// Dont forget to close the stream &lt;/span&gt;
&lt;/pre&gt;

If we are looking for performance, we can use the &lt;em&gt;MemoryStream&lt;/em&gt; and the &lt;em&gt;BufferedStream&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Creating the MemoryStream object&lt;/span&gt;
MemoryStream ms = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
&amp;nbsp;
&lt;span class="rem"&gt;// Using one StreamWriter for access the MemoryStream&lt;/span&gt;
StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(ms);
sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
sw.Flush();
&amp;nbsp;
&lt;span class="rem"&gt;// Now, we can use the MemoryStream to flush the content to a file at once&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;@"c:\temp\filename2.txt"&lt;/span&gt;);
ms.WriteTo(fs);
fs.Close();
&amp;nbsp;
sw.Close(); &lt;span class="rem"&gt;// This also closes the MemoryStream (the underlying stream)&lt;/span&gt;
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the stream we want to buffer&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;@"c:\temp\filename2.txt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creates the BufferedStream&lt;/span&gt;
BufferedStream bs = &lt;span class="kwrd"&gt;new&lt;/span&gt; BufferedStream(fs);
&amp;nbsp;
&lt;span class="rem"&gt;// Now, perform some writing operation&lt;/span&gt;
StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(bs);
sw.WriteLine(&lt;span class="str"&gt;"test line"&lt;/span&gt;);
sw.Close(); &lt;span class="rem"&gt;// This also closes the BufferedStream and the FileStream (the underlying stream)&lt;/span&gt;
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the stream we want to buffer&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;@"c:\temp\filename2.txt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creates the BufferedStream&lt;/span&gt;
BufferedStream bs = &lt;span class="kwrd"&gt;new&lt;/span&gt; BufferedStream(fs);
&amp;nbsp;
&lt;span class="rem"&gt;// Now, perform some reading operation&lt;/span&gt;
StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(bs);
MessageBox.Show(sr.ReadLine());
sr.Close(); &lt;span class="rem"&gt;// This also closes the BufferedStream and the FileStream (the underlying stream)&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Compressing and Decompressing streams&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

We can use the &lt;em&gt;GZipStream&lt;/em&gt; and &lt;em&gt;DeflateStream&lt;/em&gt; classes for performing compression and decompression of streams:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the stream we want to compress&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;@"c:\temp\filename.zip"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creates the GZipStream&lt;/span&gt;
GZipStream gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(fs, CompressionMode.Compress);
&amp;nbsp;
&lt;span class="rem"&gt;// Reading the content to compress&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; s = File.ReadAllText(&lt;span class="str"&gt;@"c:\temp\filename.txt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Writing compressed content&lt;/span&gt;
StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(gzip);
sw.Write(s);
sw.Close();  &lt;span class="rem"&gt;// This also closes the GZipStream and the FileStream (the underlying stream)&lt;/span&gt;
&lt;/pre&gt;

Binary compression, using bytes:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the stream we want to compress&lt;/span&gt;
FileStream fs = File.Create(&lt;span class="str"&gt;@"c:\temp\filename.zip"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creates the GZipStream&lt;/span&gt;
GZipStream gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(fs, CompressionMode.Compress);
&amp;nbsp;
&lt;span class="rem"&gt;// Reading the content to compress&lt;/span&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] bytes = File.ReadAllBytes(&lt;span class="str"&gt;@"c:\temp\filename.txt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Writing compressed content&lt;/span&gt;
gzip.Write(bytes, 0, bytes.Length);
gzip.Close();  &lt;span class="rem"&gt;// This also closes the FileStream (the underlying stream)&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Decompression&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the stream we want to decompress&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;@"c:\temp\filename.zip"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creates the GZipStream&lt;/span&gt;
GZipStream gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(fs, CompressionMode.Decompress);
&amp;nbsp;
&lt;span class="rem"&gt;// Reading the uncompressed content&lt;/span&gt;
StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(gzip);
MessageBox.Show(sr.ReadToEnd());
sr.Close();  &lt;span class="rem"&gt;// This also closes the GZipStream and the FileStream (the underlying stream)&lt;/span&gt;
&lt;/pre&gt;

Binary decompression, using bytes:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the stream we want to decompress&lt;/span&gt;
FileStream fs = File.OpenRead(&lt;span class="str"&gt;@"c:\temp\filename.zip"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creates the GZipStream&lt;/span&gt;
GZipStream gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(fs, CompressionMode.Decompress);
&amp;nbsp;
&lt;span class="rem"&gt;// We want to read binary content into one memory stream&lt;/span&gt;
&lt;span class="rem"&gt;// This could be also a FileStream object&lt;/span&gt;
MemoryStream ms = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
&amp;nbsp;
&lt;span class="rem"&gt;// Reading the uncompressed content&lt;/span&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt; c = gzip.ReadByte();
&lt;span class="kwrd"&gt;while&lt;/span&gt; (c != -1)
{
    ms.WriteByte((&lt;span class="kwrd"&gt;byte&lt;/span&gt;)c);
    c = gzip.ReadByte();
}
&amp;nbsp;
&lt;span class="rem"&gt;// Show read content's length&lt;/span&gt;
MessageBox.Show(ms.Length.ToString());
ms.Close(); &lt;span class="rem"&gt;// Close our target stream&lt;/span&gt;
&amp;nbsp;
gzip.Close();  &lt;span class="rem"&gt;// This also closes the FileStream (the underlying stream)&lt;/span&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8087183404482794607?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8087183404482794607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8087183404482794607' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8087183404482794607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8087183404482794607'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/streams.html' title='Streams'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6940162452586467266</id><published>2008-01-23T07:27:00.000-08:00</published><updated>2008-01-23T07:39:15.812-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>The FileSystemWatcher class</title><content type='html'>By using the FileSystemWatcher we can monitor the activity in our disks.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Create our file system watcher&lt;/span&gt;
FileSystemWatcher fsw = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemWatcher(&lt;span class="str"&gt;@"C:\temp"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Also, we want to include subdirectories&lt;/span&gt;
fsw.IncludeSubdirectories = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// Subscribing to events&lt;/span&gt;
fsw.Changed += &lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemEventHandler(fsw_Changed);
fsw.Created += &lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemEventHandler(fsw_Created);
fsw.Renamed += &lt;span class="kwrd"&gt;new&lt;/span&gt; RenamedEventHandler(fsw_Renamed);
fsw.Deleted += &lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemEventHandler(fsw_Deleted);
&amp;nbsp;
&lt;span class="rem"&gt;// Enabling raising events&lt;/span&gt;
fsw.EnableRaisingEvents = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Here the events handlers&lt;/span&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; fsw_Deleted(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, FileSystemEventArgs e)
{
    MessageBox.Show(&lt;span class="str"&gt;"Deleted "&lt;/span&gt; + e.FullPath);
}
&amp;nbsp;
&lt;span class="kwrd"&gt;void&lt;/span&gt; fsw_Renamed(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RenamedEventArgs e)
{
    MessageBox.Show(&lt;span class="str"&gt;"Renamed "&lt;/span&gt; + e.OldName + &lt;span class="str"&gt;" to "&lt;/span&gt; + e.Name);
}
&amp;nbsp;
&lt;span class="kwrd"&gt;void&lt;/span&gt; fsw_Created(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, FileSystemEventArgs e)
{
    MessageBox.Show(&lt;span class="str"&gt;"Created "&lt;/span&gt; + e.Name);
}
&amp;nbsp;
&lt;span class="kwrd"&gt;void&lt;/span&gt; fsw_Changed(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, FileSystemEventArgs e)
{
    MessageBox.Show(&lt;span class="str"&gt;"Changed "&lt;/span&gt; + e.Name);
}
&lt;/pre&gt;

We can polling for changes detection:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Creating our file system watcher&lt;/span&gt;
FileSystemWatcher fsw = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileSystemWatcher(&lt;span class="str"&gt;@"C:\temp"&lt;/span&gt;);
fsw.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.FileName;
&amp;nbsp;
&lt;span class="rem"&gt;// Creating our waiting handler&lt;/span&gt;
&lt;span class="rem"&gt;// We set 100 seconds for timeout and&lt;/span&gt;
&lt;span class="rem"&gt;// we are waiting for all kind of changes&lt;/span&gt;
WaitForChangedResult wfcr = fsw.WaitForChanged(WatcherChangeTypes.All, 100000);
&amp;nbsp;
&lt;span class="rem"&gt;// Showing the result&lt;/span&gt;
MessageBox.Show(wfcr.ChangeType.ToString());
MessageBox.Show(wfcr.Name);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6940162452586467266?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6940162452586467266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6940162452586467266' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6940162452586467266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6940162452586467266'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/filesystemwatcher-class.html' title='The FileSystemWatcher class'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5151129338765360302</id><published>2008-01-22T19:21:00.001-08:00</published><updated>2008-01-23T07:26:17.597-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>FileInfo, DirectoryInfo and DriveInfo classes</title><content type='html'>&lt;em&gt;FileSystemInfo&lt;/em&gt; is the base class of &lt;em&gt;FileInfo&lt;/em&gt; and &lt;em&gt;DriveInfo&lt;/em&gt;. Here, some important properties and methods:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Attributes:&lt;/strong&gt; Gets or sets &lt;em&gt;FileAttributes&lt;/em&gt; of the current file or directory. &lt;/li&gt;
&amp;nbsp; 
&lt;li&gt;&lt;strong&gt;Name:&lt;/strong&gt; Gets the simple name for the file or directory. For a file, this is the name within the directory. For a directory, this is the last directory name in the directory hierarchy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FullName:&lt;/strong&gt; Gets the full path to the file or directory. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extension:&lt;/strong&gt; Gets a string representation of the extension part of the file or directory. &lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;LastWriteTime:&lt;/strong&gt; (!) Gets or sets the time the file or directory was last written to. &lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Exists:&lt;/strong&gt; Determines whether the file or directory exists. &lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Delete():&lt;/strong&gt; Removes the file or directory from the file system. &lt;/li&gt;
&lt;/ul&gt;

The &lt;em&gt;FileInfo&lt;/em&gt; also has also some interesting properties and methods:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Directory:&lt;/strong&gt; (!) Gets the &lt;em&gt;DirectoryInfo&lt;/em&gt; object that represents the directory that this file is stored within.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;DirectoryName:&lt;/strong&gt; Gets the name of the directory that this file is stored within.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Length:&lt;/strong&gt; Gets the length of the file.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;AppendText():&lt;/strong&gt; Creates a new &lt;em&gt;StreamWriter&lt;/em&gt; that will allow appending text to the file. &lt;em&gt;!!! Default Encoding is UTF-8 !!!&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CreateText():&lt;/strong&gt; Creates a new &lt;em&gt;StreamWriter&lt;/em&gt; and a new file for writing text. &lt;em&gt;!!! Default Encoding is UTF-8 !!!&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenText():&lt;/strong&gt; Opens the file and returns a &lt;em&gt;StreamReader&lt;/em&gt; to allow reading of text within the file. &lt;em&gt;!!! Default Encoding is UTF-8 !!!&lt;/em&gt;&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Open():&lt;/strong&gt; Opens the file with specific privileges (read, read/write, and so on). Returns a new &lt;em&gt;FileStream&lt;/em&gt; object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenRead():&lt;/strong&gt; Opens the file with read-only access. Returns a new &lt;em&gt;FileStream&lt;/em&gt; object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OpenWrite():&lt;/strong&gt; Opens the file with write-only access. Returns a new &lt;em&gt;FileStream&lt;/em&gt; object.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;CopyTo():&lt;/strong&gt; Makes a copy of the file in a new location.
MoveTo Moves the file to a new location.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replace():&lt;/strong&gt; Replaces a file with the information in the current FileInfo object.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create():&lt;/strong&gt; Creates a file based on the current file information. Returns a new &lt;em&gt;FileStream&lt;/em&gt; object.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Decrypt():&lt;/strong&gt; Decrypts a file that was encrypted by the current user.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encrypt():&lt;/strong&gt; Encrypts a file so that only the current user can decrypt the&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting information from a file&lt;/span&gt;
FileInfo fi = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileInfo(&lt;span class="str"&gt;@"C:\temp\filename.txt"&lt;/span&gt;);
&amp;nbsp;
MessageBox.Show(fi.LastWriteTime.ToString());
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Append text to one existing file&lt;/span&gt;
FileInfo fi = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileInfo(&lt;span class="str"&gt;@"C:\temp\filename.txt"&lt;/span&gt;);
&amp;nbsp;
StreamWriter sw = fi.AppendText();
sw.WriteLine(&lt;span class="str"&gt;"another line"&lt;/span&gt;);
sw.Flush(); &lt;span class="rem"&gt;// If we don't want to flush manually, set the AutoFlush property as true&lt;/span&gt;
sw.Close(); &lt;span class="rem"&gt;// don't forget to close the stream&lt;/span&gt;
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Reading content from a file&lt;/span&gt;
FileInfo fi = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileInfo(&lt;span class="str"&gt;@"C:\temp\filename.txt"&lt;/span&gt;);
&amp;nbsp;
StreamReader sr = fi.OpenText();
MessageBox.Show(sr.ReadToEnd());
sr.Close(); &lt;span class="rem"&gt;// don't forget to close the stream&lt;/span&gt;
&lt;/pre&gt;

The &lt;em&gt;DirectoryInfo&lt;/em&gt; also has also some interesting properties and methods:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parent:&lt;/strong&gt; Gets the &lt;em&gt;DirectoryInfo&lt;/em&gt; object for the parent directory of the current directory in the directory hierarchy &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Root:&lt;/strong&gt; Gets the root part of the directory’s path as a string&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;Create():&lt;/strong&gt; Creates the directory described in the current &lt;em&gt;DirectoryInfo&lt;/em&gt; object&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CreateSubdirectory():&lt;/strong&gt; (!) Creates a new directory as a child directory of the current directory in the directory hierarchy&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;GetDirectories():&lt;/strong&gt; Retrieves an array of &lt;em&gt;DirectoryInfo&lt;/em&gt; objects that represent subdirectories of the current directory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetFiles():&lt;/strong&gt; (!) Retrieves an array of FileInfo objects that represent all the files in the current directory&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting directory information&lt;/span&gt;
DirectoryInfo di = &lt;span class="kwrd"&gt;new&lt;/span&gt; DirectoryInfo(&lt;span class="str"&gt;@"C:\temp"&lt;/span&gt;);
&amp;nbsp;
MessageBox.Show(di.Parent.Name);
&amp;nbsp;
&lt;span class="rem"&gt;// Get all txt files from directory&lt;/span&gt;
FileInfo[] fis = di.GetFiles(&lt;span class="str"&gt;"*.txt"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (FileInfo fi0 &lt;span class="kwrd"&gt;in&lt;/span&gt; fis)
    MessageBox.Show(fi0.Name);
&lt;/pre&gt;

And finally, for the &lt;em&gt;DriveInfo&lt;/em&gt; also has also some interesting properties and methods:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AvailableFreeSpace:&lt;/strong&gt; Gets the amount of available space on the drive. The amount might be different from the amount returned by &lt;em&gt;TotalFreeSpace&lt;/em&gt;, depending on disk quotas or depending on the &lt;em&gt;IsolatedStore&lt;/em&gt; we are working on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TotalFreeSpace:&lt;/strong&gt; Gets the total amount of free space on the drive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TotalSize:&lt;/strong&gt; Gets the total size of the drive.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;DriveType:&lt;/strong&gt; Gets the type of drive in the form of the DriveType enumeration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IsReady:&lt;/strong&gt; Gets the status of the drive, indicating whether it is ready to be accessed.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;RootDirectory:&lt;/strong&gt; Gets a DirectoryInfo object that represents the root directory of the drive. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetDrives():&lt;/strong&gt; A static method that returns all the drives on the current system.&lt;/li&gt;
&lt;/ul&gt;

The &lt;em&gt;DriveType&lt;/em&gt; enumeration:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CDRom:&lt;/strong&gt; An optical drive. It can be CD-ROM, DVD, and so on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fixed:&lt;/strong&gt; A fixed disk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network:&lt;/strong&gt; A network mapped drive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NoRootDirectory:&lt;/strong&gt; A drive that does not have a root directory.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ram:&lt;/strong&gt; A RAM drive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Removable:&lt;/strong&gt; A drive that has removable media.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unknown:&lt;/strong&gt; The drive could not be determined.&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting some information from drive&lt;/span&gt;
DriveInfo dri = &lt;span class="kwrd"&gt;new&lt;/span&gt; DriveInfo(&lt;span class="str"&gt;"C"&lt;/span&gt;);
&amp;nbsp;
MessageBox.Show(&lt;span class="str"&gt;"Total Space="&lt;/span&gt; + dri.TotalSize.ToString()
    + &lt;span class="str"&gt;" TotalFreeSpace="&lt;/span&gt; + dri.TotalFreeSpace.ToString()
    + &lt;span class="str"&gt;" AvailableFreeSpace="&lt;/span&gt; + dri.AvailableFreeSpace.ToString());
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Reading all drives we have&lt;/span&gt;
DriveInfo[] dris = DriveInfo.GetDrives();
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DriveInfo dri0 &lt;span class="kwrd"&gt;in&lt;/span&gt; dris)
    MessageBox.Show(dri0.Name + &lt;span class="str"&gt;" type="&lt;/span&gt; + dri0.DriveType.ToString());
&lt;/pre&gt;

Here the &lt;em&gt;Path&lt;/em&gt; class methods and properties:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GetFileName():&lt;/strong&gt; Returns the name of the file in the specified path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetDirectoryName():&lt;/strong&gt; Returns the name of the directory in the specified path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetExtension():&lt;/strong&gt; Returns the name of the file extension in the specified path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetFileNameWithoutExtension():&lt;/strong&gt; Returns the file name without the extension in the specified path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ChangeExtension():&lt;/strong&gt; Takes a path and returns a new path with the file name’s extension changed.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;GetFullPath():&lt;/strong&gt; Returns a full path to the specified path. This method can be used to resolve relative paths.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetPathRoot():&lt;/strong&gt; Returns the root directory name in the specified path.&lt;/li&gt;
&amp;nbsp;
&lt;li&gt;&lt;strong&gt;GetRandomFileName():&lt;/strong&gt; Generates a random file name.  &lt;em&gt;!!! Without path !!!&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetTempFileName():&lt;/strong&gt; Generates a temporary file in the file system and returns the &lt;em&gt;full path&lt;/em&gt; to the file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GetTempPath():&lt;/strong&gt; Returns the path to the temporary file directory for the current user or system. &lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting some information from files&lt;/span&gt;
MessageBox.Show(Path.GetDirectoryName(&lt;span class="str"&gt;"c:\\temp\\filename.txt"&lt;/span&gt;));
MessageBox.Show(Path.GetFileName(&lt;span class="str"&gt;"c:\\temp\\filename.txt"&lt;/span&gt;));
MessageBox.Show(Path.ChangeExtension(&lt;span class="str"&gt;"c:\\temp\\filename.txt"&lt;/span&gt;, &lt;span class="str"&gt;".ccc"&lt;/span&gt;));
&amp;nbsp;
&lt;span class="rem"&gt;// Getting random and temporary filenames&lt;/span&gt;
MessageBox.Show(Path.GetRandomFileName());
MessageBox.Show(Path.GetTempFileName());
MessageBox.Show(Path.GetTempPath());
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5151129338765360302?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5151129338765360302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5151129338765360302' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5151129338765360302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5151129338765360302'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/fileinfo-directoryinfo-and-driveinfo.html' title='FileInfo, DirectoryInfo and DriveInfo classes'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-1883673273702232028</id><published>2008-01-21T16:59:00.000-08:00</published><updated>2008-01-21T17:30:31.750-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Windows Management Instrumentation</title><content type='html'>Getting information from WMI objects:

&lt;pre class="csharpcode"&gt;
ManagementObjectSearcher s = &lt;span class="kwrd"&gt;new&lt;/span&gt; ManagementObjectSearcher(&lt;span class="str"&gt;"SELECT * FROM Win32_Service WHERE Started = TRUE"&lt;/span&gt;);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ManagementObject service &lt;span class="kwrd"&gt;in&lt;/span&gt; s.Get())
{
    &lt;span class="rem"&gt;// Show some information&lt;/span&gt;
    MessageBox.Show(service[&lt;span class="str"&gt;"Caption"&lt;/span&gt;].ToString());
}
&lt;/pre&gt;

Or using the &lt;em&gt;SelectQuery&lt;/em&gt; object:

&lt;pre class="csharpcode"&gt;
SelectQuery query = &lt;span class="kwrd"&gt;new&lt;/span&gt; SelectQuery(&lt;span class="str"&gt;"Win32_Service"&lt;/span&gt;, &lt;span class="str"&gt;"State='Running'"&lt;/span&gt;);
&amp;nbsp;
ManagementObjectSearcher s = &lt;span class="kwrd"&gt;new&lt;/span&gt; ManagementObjectSearcher(query);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ManagementObject service &lt;span class="kwrd"&gt;in&lt;/span&gt; s.Get())
{
    MessageBox.Show(service.Properties[&lt;span class="str"&gt;"Caption"&lt;/span&gt;].Value.ToString());
}
&lt;/pre&gt;

Changing some properties:

&lt;pre class="csharpcode"&gt;
ManagementObjectSearcher s = &lt;span class="kwrd"&gt;new&lt;/span&gt; ManagementObjectSearcher(&lt;span class="str"&gt;"SELECT * FROM Win32_Service WHERE Name = 'InfonetSvc'"&lt;/span&gt;);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ManagementObject service &lt;span class="kwrd"&gt;in&lt;/span&gt; s.Get())
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (service[&lt;span class="str"&gt;"StartMode"&lt;/span&gt;].ToString() == &lt;span class="str"&gt;"Manual"&lt;/span&gt;)
        service.InvokeMethod(&lt;span class="str"&gt;"ChangeStartMode"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { &lt;span class="str"&gt;"Automatic"&lt;/span&gt; });
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        service.InvokeMethod(&lt;span class="str"&gt;"ChangeStartMode"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { &lt;span class="str"&gt;"Manual"&lt;/span&gt; });
}
&lt;/pre&gt;

Or, if property is &lt;em&gt;Read/write&lt;/em&gt; access type we can use the Put method directly:

&lt;pre class="csharpcode"&gt;
ManagementObjectSearcher s = &lt;span class="kwrd"&gt;new&lt;/span&gt; ManagementObjectSearcher(&lt;span class="str"&gt;"SELECT * FROM Win32_Environment WHERE Name = 'myVar'"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ManagementObject env &lt;span class="kwrd"&gt;in&lt;/span&gt; s.Get())
{
    &lt;span class="rem"&gt;// show the instance&lt;/span&gt;
    MessageBox.Show(env[&lt;span class="str"&gt;"VariableValue"&lt;/span&gt;].ToString());
&amp;nbsp;
    env[&lt;span class="str"&gt;"VariableValue"&lt;/span&gt;] = &lt;span class="str"&gt;"new value"&lt;/span&gt;;
    env.Put();
}
&lt;/pre&gt;

Subscribing to events:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Our event query&lt;/span&gt;
EventQuery query = &lt;span class="kwrd"&gt;new&lt;/span&gt; EventQuery();
query.QueryString = &lt;span class="str"&gt;"SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance isa \"Win32_Process\""&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// Initialize an event watcher and subscribe to events &lt;/span&gt;
&lt;span class="rem"&gt;// that match this query&lt;/span&gt;
ManagementEventWatcher watcher = &lt;span class="kwrd"&gt;new&lt;/span&gt; ManagementEventWatcher(query);
&amp;nbsp;
&lt;span class="rem"&gt;// times out watcher.WaitForNextEvent in 50 seconds&lt;/span&gt;
watcher.Options.Timeout = &lt;span class="kwrd"&gt;new&lt;/span&gt; TimeSpan(0, 0, 50);
&amp;nbsp;
&lt;span class="rem"&gt;// Block until the next event occurs &lt;/span&gt;
&lt;span class="rem"&gt;// Note: this can be done in a loop if waiting for &lt;/span&gt;
&lt;span class="rem"&gt;//        more than one occurrence&lt;/span&gt;
MessageBox.Show(&lt;span class="str"&gt;"Open an application (notepad.exe) to trigger an event."&lt;/span&gt;);
ManagementBaseObject e = watcher.WaitForNextEvent();
&amp;nbsp;
&lt;span class="rem"&gt;//Display information from the event&lt;/span&gt;
MessageBox.Show(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(
    &lt;span class="str"&gt;"Process {0} has been created, path is: {1}"&lt;/span&gt;,
    ((ManagementBaseObject)e
    [&lt;span class="str"&gt;"TargetInstance"&lt;/span&gt;])[&lt;span class="str"&gt;"Name"&lt;/span&gt;],
    ((ManagementBaseObject)e
    [&lt;span class="str"&gt;"TargetInstance"&lt;/span&gt;])[&lt;span class="str"&gt;"ExecutablePath"&lt;/span&gt;]));
&amp;nbsp;
&lt;span class="rem"&gt;//Cancel the subscription&lt;/span&gt;
watcher.Stop();
&lt;/pre&gt;

If we need user's credentials:

&lt;pre class="csharpcode"&gt;
ConnectionOptions connOptions = &lt;span class="kwrd"&gt;new&lt;/span&gt; ConnectionOptions();
connOptions.Username = &lt;span class="str"&gt;"username"&lt;/span&gt;;
connOptions.Password = &lt;span class="str"&gt;"password"&lt;/span&gt;;
ManagementScope mScope = &lt;span class="kwrd"&gt;new&lt;/span&gt; ManagementScope(&lt;span class="str"&gt;"\\machinename"&lt;/span&gt;, connOptions);
&amp;nbsp;
ObjectQuery oQuery = &lt;span class="kwrd"&gt;new&lt;/span&gt; ObjectQuery(&lt;span class="str"&gt;"SELECT Size, Name FROM Win32_LogicalDisk where DriveType=3"&lt;/span&gt;);
&amp;nbsp;
ManagementObjectSearcher s = &lt;span class="kwrd"&gt;new&lt;/span&gt; ManagementObjectSearcher(mScope, oQuery);
ManagementObjectCollection AllObjects = s.Get();
&amp;nbsp;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ManagementObject mObject &lt;span class="kwrd"&gt;in&lt;/span&gt; AllObjects)
{
    MessageBox.Show(&lt;span class="str"&gt;"Resource Name: "&lt;/span&gt; + mObject[&lt;span class="str"&gt;"Name"&lt;/span&gt;].ToString());
    MessageBox.Show(&lt;span class="str"&gt;"Resource Size: "&lt;/span&gt; + mObject[&lt;span class="str"&gt;"Size"&lt;/span&gt;].ToString());
}
&lt;/pre&gt;

More information on &lt;a href="http://msdn2.microsoft.com/en-us/library/system.management.aspx"&gt;MSDN&lt;/a&gt;
Available WMI classes in &lt;a href="http://msdn2.microsoft.com/en-us/library/aa394554(VS.85).aspx"&gt;MSDN&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-1883673273702232028?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/1883673273702232028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=1883673273702232028' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1883673273702232028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1883673273702232028'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/windows-management-instrumentation.html' title='Windows Management Instrumentation'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6032658177204018118</id><published>2008-01-21T10:32:00.000-08:00</published><updated>2008-02-09T09:42:03.171-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Performance Counters</title><content type='html'>&lt;strong&gt;Creating a counter:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Creating our category&lt;/span&gt;
PerformanceCounterCategory.Create(&lt;span class="str"&gt;"MyCategory"&lt;/span&gt;, &lt;span class="rem"&gt;// category name&lt;/span&gt;
    &lt;span class="str"&gt;"My New Perf Category Description"&lt;/span&gt;,  &lt;span class="rem"&gt;// category help&lt;/span&gt;
    PerformanceCounterCategoryType.SingleInstance, &lt;span class="rem"&gt;// single instance&lt;/span&gt;
    &lt;span class="str"&gt;"MyCounter"&lt;/span&gt;, &lt;span class="rem"&gt;// counter name&lt;/span&gt;
    &lt;span class="str"&gt;"My New Perf Counter Desc"&lt;/span&gt;);  &lt;span class="rem"&gt;// counter help&lt;/span&gt;
&lt;/pre&gt;

We can set the &lt;em&gt;Multiple Instance&lt;/em&gt; property if we want to reuse the same counter from differences sources.  Example; in a multiprocessor environment, we can name instances for every processor we have:  &lt;em&gt;processor 1&lt;/em&gt;, &lt;em&gt;processor 2&lt;/em&gt;, etc.&lt;br&gt;&lt;br&gt;

We can also create multiple categories at once by using the &lt;em&gt;CounterCreationDataCollection&lt;/em&gt; parameter in the method &lt;em&gt;PerformanceCounterCategory.Create&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Deleting one category:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
PerformanceCounterCategory.Delete(&lt;span class="str"&gt;"MyCategory"&lt;/span&gt;);
&lt;/pre&gt;

&lt;strong&gt;Asking for one counter:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (PerformanceCounterCategory.Exists(&lt;span class="str"&gt;"MyCategory"&lt;/span&gt;))
{
    PerformanceCounterCategory pcat = &lt;span class="kwrd"&gt;new&lt;/span&gt; PerformanceCounterCategory(&lt;span class="str"&gt;"MyCategory"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (pcat.CounterExists(&lt;span class="str"&gt;"myCounter"&lt;/span&gt;))
    {
        ...
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        MessageBox.Show(&lt;span class="str"&gt;"Counter doesn't exists"&lt;/span&gt;);
}
&lt;span class="kwrd"&gt;else&lt;/span&gt;
    MessageBox.Show(&lt;span class="str"&gt;"Category doesn't exists"&lt;/span&gt;);
&lt;/pre&gt;

We can get multiple categories and counters:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
PerformanceCounterCategory[] pcats = PerformanceCounterCategory.GetCategories();
PerformanceCounter[] pcount = pcat.GetCounters();
&lt;/pre&gt;

&lt;strong&gt;Reading a counter's value:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
PerformanceCounter pc = &lt;span class="kwrd"&gt;new&lt;/span&gt; PerformanceCounter(&lt;span class="str"&gt;"MyCategory"&lt;/span&gt;, &lt;span class="str"&gt;"myCounter"&lt;/span&gt;);
MessageBox.Show(pc.CounterName + &lt;span class="str"&gt;" value="&lt;/span&gt; + pc.NextValue().ToString());
&lt;/pre&gt;

&lt;strong&gt;Increasing a counter:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// get an instance of our perf counter&lt;/span&gt;
PerformanceCounter counter = &lt;span class="kwrd"&gt;new&lt;/span&gt; PerformanceCounter(&lt;span class="str"&gt;"MyCategory"&lt;/span&gt;, &lt;span class="str"&gt;"myCounter"&lt;/span&gt;);
&amp;nbsp;
counter.ReadOnly = &lt;span class="kwrd"&gt;false&lt;/span&gt;; &lt;span class="rem"&gt;// Set false for writing to it&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// increment and close the perf counter&lt;/span&gt;
counter.Increment();
counter.Close();
&lt;/pre&gt;

We can set data directly by using the property &lt;em&gt;RawValue&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

If we are using multiple instances, we need to specify which instance is the counter related to:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
counter.InstanceName = &lt;span class="str"&gt;"testt"&lt;/span&gt;;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6032658177204018118?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6032658177204018118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6032658177204018118' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6032658177204018118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6032658177204018118'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/performance-counters.html' title='Performance Counters'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-1863281586633852749</id><published>2008-01-20T18:10:00.000-08:00</published><updated>2008-02-09T09:42:48.086-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Process management</title><content type='html'>&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting information about the current process&lt;/span&gt;
Process cp = Process.GetCurrentProcess();
MessageBox.Show(cp.Id.ToString());
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting a process by it's Id&lt;/span&gt;
&lt;span class="kwrd"&gt;try&lt;/span&gt;
{
    Process pid = Process.GetProcessById(3660);
&amp;nbsp;
    MessageBox.Show(pid.ProcessName);
}
&lt;span class="kwrd"&gt;catch&lt;/span&gt;(ArgumentException)
{
    &lt;span class="rem"&gt;// Process with this Id was not found&lt;/span&gt;
}
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting all process by name&lt;/span&gt;
Process[] pcol = Process.GetProcessesByName(&lt;span class="str"&gt;"iexplore"&lt;/span&gt;);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Process p &lt;span class="kwrd"&gt;in&lt;/span&gt; pcol)
    MessageBox.Show(p.Id.ToString());
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting all process in another computer&lt;/span&gt;
Process[] pcol = Process.GetProcesses(&lt;span class="str"&gt;"pcname"&lt;/span&gt;);
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Process p &lt;span class="kwrd"&gt;in&lt;/span&gt; pcol)
    MessageBox.Show(p.ProcessName);
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Launching a new process&lt;/span&gt;
Process p2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Process();
ProcessStartInfo psi = &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessStartInfo(&lt;span class="str"&gt;"notepad.exe"&lt;/span&gt;);
p2.StartInfo = psi;
p2.Start();
&lt;/pre&gt;

For launch a process with user's credentials, we can use:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Launching a new process&lt;/span&gt;
Process p2 = &lt;span class="kwrd"&gt;new&lt;/span&gt; Process();
ProcessStartInfo psi = &lt;span class="kwrd"&gt;new&lt;/span&gt; ProcessStartInfo(&lt;span class="str"&gt;"notepad.exe"&lt;/span&gt;);
p2.StartInfo = psi;
&amp;nbsp;
&lt;span class="rem"&gt;// Setting the username and password&lt;/span&gt;
psi.UserName = &lt;span class="str"&gt;"username"&lt;/span&gt;;
psi.Domain = &lt;span class="str"&gt;"domain"&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// Password must be secured&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; pwd = &lt;span class="str"&gt;"password"&lt;/span&gt;;
&lt;span class="kwrd"&gt;char&lt;/span&gt;[] cpwd = pwd.ToCharArray();
&amp;nbsp;
SecureString ss = &lt;span class="kwrd"&gt;new&lt;/span&gt; SecureString();
&amp;nbsp;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;char&lt;/span&gt; c &lt;span class="kwrd"&gt;in&lt;/span&gt; cpwd)
    ss.AppendChar(c);
&amp;nbsp;
psi.Password = ss;
&amp;nbsp;
&lt;span class="rem"&gt;// UseShellExecute must be false if we want to execute the process with user's credentials&lt;/span&gt;
psi.UseShellExecute = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
&amp;nbsp;
p2.Start();
&amp;nbsp;
&lt;span class="rem"&gt;// Waiting until the program finishes&lt;/span&gt;
p2.WaitForExit();
&lt;/pre&gt;

Or simply:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Password must be secured&lt;/span&gt;
&lt;span class="kwrd"&gt;string&lt;/span&gt; pwd = &lt;span class="str"&gt;"password"&lt;/span&gt;;
&lt;span class="kwrd"&gt;char&lt;/span&gt;[] cpwd = pwd.ToCharArray();
&amp;nbsp;
SecureString ss = &lt;span class="kwrd"&gt;new&lt;/span&gt; SecureString();
&amp;nbsp;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;char&lt;/span&gt; c &lt;span class="kwrd"&gt;in&lt;/span&gt; cpwd)
    ss.AppendChar(c);
&amp;nbsp;
&lt;span class="rem"&gt;// Launch the process with user's credentials&lt;/span&gt;
Process.Start(&lt;span class="str"&gt;"notepad.exe"&lt;/span&gt;, &lt;span class="str"&gt;"username"&lt;/span&gt;, ss, &lt;span class="str"&gt;"domain"&lt;/span&gt;);
&lt;/pre&gt;

Other useful methods and properties:&lt;br&gt;&lt;br&gt;

&lt;em&gt;WaitForExit&lt;br&gt;
WaitForInputIdle&lt;br&gt;
Kill&lt;br&gt;
ExitCode&lt;br&gt;
HasExited&lt;br&gt;
Threads&lt;/em&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-1863281586633852749?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/1863281586633852749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=1863281586633852749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1863281586633852749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1863281586633852749'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/process-management.html' title='Process management'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5902810801182247667</id><published>2008-01-20T13:19:00.000-08:00</published><updated>2008-02-09T09:44:24.264-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>About Trace Listeners</title><content type='html'>By using trace listeners we can achieve debugging and tracing tasks in the easy way.  We can configure trace listeners by source code or at runtime using the application config file (app.config).&lt;br&gt;&lt;br&gt;

&lt;em&gt;The source code method:&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// First step: create the trace source object&lt;/span&gt;
TraceSource ts = &lt;span class="kwrd"&gt;new&lt;/span&gt; TraceSource(&lt;span class="str"&gt;"myTraceSource"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Second step: create some trace listeners&lt;/span&gt;
TextWriterTraceListener tr = &lt;span class="kwrd"&gt;new&lt;/span&gt; TextWriterTraceListener(&lt;span class="str"&gt;"C:\\outfile.txt"&lt;/span&gt;);
XmlWriterTraceListener xt = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlWriterTraceListener(&lt;span class="str"&gt;"C:\\outfile.xml"&lt;/span&gt;);
DelimitedListTraceListener dt = &lt;span class="kwrd"&gt;new&lt;/span&gt; DelimitedListTraceListener(&lt;span class="str"&gt;"C:\\outfile.csv.txt"&lt;/span&gt;);
EventLogTraceListener et = &lt;span class="kwrd"&gt;new&lt;/span&gt; EventLogTraceListener(&lt;span class="str"&gt;"myappp"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Third step: configuring our trace source and trace listeners&lt;/span&gt;
ts.Switch = &lt;span class="kwrd"&gt;new&lt;/span&gt; SourceSwitch(&lt;span class="str"&gt;"mySwitch"&lt;/span&gt;, &lt;span class="str"&gt;"my switch"&lt;/span&gt;);
ts.Switch.Level = SourceLevels.Warning; &lt;span class="rem"&gt;// Enable only warning, error and critical events&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Configuring trace listeners&lt;/span&gt;
dt.Delimiter = &lt;span class="str"&gt;"|"&lt;/span&gt;;
dt.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.Timestamp;
xt.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.Timestamp;
tr.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.Timestamp | TraceOptions.Callstack;
&amp;nbsp;
&lt;span class="rem"&gt;// Adding our trace listeners&lt;/span&gt;
ts.Listeners.Clear();
ts.Listeners.Add(et);
ts.Listeners.Add(dt);
ts.Listeners.Add(tr);
ts.Listeners.Add(xt);
&amp;nbsp;
&lt;span class="rem"&gt;// Setting autoflush to save files automatically&lt;/span&gt;
Trace.AutoFlush = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// Writing out some events&lt;/span&gt;
ts.TraceEvent(TraceEventType.Warning, 0, &lt;span class="str"&gt;"warning message"&lt;/span&gt;);
ts.TraceEvent(TraceEventType.Error, 0, &lt;span class="str"&gt;"error message"&lt;/span&gt;);
ts.TraceEvent(TraceEventType.Information, 0, &lt;span class="str"&gt;"information message"&lt;/span&gt;);
ts.TraceEvent(TraceEventType.Critical, 0, &lt;span class="str"&gt;"critical message"&lt;/span&gt;);
&lt;/pre&gt;

&lt;em&gt;The application configuration file method:&lt;/em&gt;&lt;br&gt;&lt;br&gt;

We can achieve the same task above using the application configuration file.  This allow you to change settings at runtime when you need some tracing information.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt; ?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.diagnostics&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;trace&lt;/span&gt; &lt;span class="attr"&gt;autoflush&lt;/span&gt;&lt;span class="kwrd"&gt;="true"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;sources&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;source&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="myTraceSource"&lt;/span&gt;
              &lt;span class="attr"&gt;switchName&lt;/span&gt;&lt;span class="kwrd"&gt;="mySwitch"&lt;/span&gt;
              &lt;span class="attr"&gt;switchType&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.SourceSwitch"&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;listeners&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;clear&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="evengloglistener"&lt;/span&gt;
            &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.EventLogTraceListener"&lt;/span&gt;
            &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="myApp"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="delimitedListener"&lt;/span&gt;
            &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.DelimitedListTraceListener"&lt;/span&gt;
            &lt;span class="attr"&gt;delimiter&lt;/span&gt;&lt;span class="kwrd"&gt;="|"&lt;/span&gt;
            &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="c:\outfile.csv.txt"&lt;/span&gt;
            &lt;span class="attr"&gt;traceOutputOptions&lt;/span&gt;&lt;span class="kwrd"&gt;="ProcessId, DateTime"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="textwriterListener"&lt;/span&gt;
            &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.TextWriterTraceListener"&lt;/span&gt;
            &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="c:\outfile.txt"&lt;/span&gt;
            &lt;span class="attr"&gt;traceOutputOptions&lt;/span&gt;&lt;span class="kwrd"&gt;="ProcessId, DateTime, Callstack"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="xmlListener"&lt;/span&gt;
            &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.XmlWriterTraceListener"&lt;/span&gt;
            &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="c:\outfile.xml"&lt;/span&gt;
            &lt;span class="attr"&gt;traceOutputOptions&lt;/span&gt;&lt;span class="kwrd"&gt;="ProcessId, DateTime"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;listeners&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;source&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;sources&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;switches&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="mySwitch"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="Warning"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;switches&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.diagnostics&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

The source code now looks simple like this:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// First step: create the trace source object&lt;/span&gt;
TraceSource ts = &lt;span class="kwrd"&gt;new&lt;/span&gt; TraceSource(&lt;span class="str"&gt;"myTraceSource"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Writing out some events&lt;/span&gt;
ts.TraceEvent(TraceEventType.Warning, 0, &lt;span class="str"&gt;"warning message"&lt;/span&gt;);
ts.TraceEvent(TraceEventType.Error, 0, &lt;span class="str"&gt;"error message"&lt;/span&gt;);
ts.TraceEvent(TraceEventType.Information, 0, &lt;span class="str"&gt;"information message"&lt;/span&gt;);
ts.TraceEvent(TraceEventType.Critical, 0, &lt;span class="str"&gt;"critical message"&lt;/span&gt;);
&lt;/pre&gt;

&lt;strong&gt;CorrelationManager&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

We can use the &lt;em&gt;CorrelationManager&lt;/em&gt; to group correlated traces.  The switch level must include the &lt;em&gt;LogicalOperationStack&lt;/em&gt; option.&lt;br&gt;&lt;br&gt;

&lt;em&gt;Using source code configuration:&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
tr.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.Timestamp | TraceOptions.LogicalOperationStack;&lt;/pre&gt;

&lt;em&gt;Or using the Application configuration file:&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="textwriterListener"&lt;/span&gt;
  &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.TextWriterTraceListener"&lt;/span&gt;
  &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="c:\outfile.txt"&lt;/span&gt;
  &lt;span class="attr"&gt;traceOutputOptions&lt;/span&gt;&lt;span class="kwrd"&gt;="ProcessId, DateTime, LogicalOperationStack"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

And the code must looks like:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Start the first logical operation&lt;/span&gt;
Trace.CorrelationManager.StartLogicalOperation(&lt;span class="str"&gt;"first logical operation"&lt;/span&gt;);
&amp;nbsp;
ts.TraceEvent(TraceEventType.Warning, 0, &lt;span class="str"&gt;"warning message"&lt;/span&gt;);
ts.TraceEvent(TraceEventType.Error, 0, &lt;span class="str"&gt;"error message"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Start a nested logical operation&lt;/span&gt;
Trace.CorrelationManager.StartLogicalOperation(&lt;span class="str"&gt;"second logical"&lt;/span&gt;);
&amp;nbsp;
ts.TraceEvent(TraceEventType.Information, 0, &lt;span class="str"&gt;"information message"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Stop the second logical operation&lt;/span&gt;
Trace.CorrelationManager.StopLogicalOperation();
&amp;nbsp;
ts.TraceEvent(TraceEventType.Critical, 0, &lt;span class="str"&gt;"critical message"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Stop the first logical operation&lt;/span&gt;
Trace.CorrelationManager.StopLogicalOperation();
&lt;/pre&gt;

Another useful technique is filter some kind of events and redirect them to one specific listener, for example, critical errors must be logged to a file and warning events to the event log only.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
tr.Filter = &lt;span class="kwrd"&gt;new&lt;/span&gt; EventTypeFilter(SourceLevels.Error);&lt;/pre&gt;

Or&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="textwriterListener"&lt;/span&gt;
  &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.TextWriterTraceListener"&lt;/span&gt;
  &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="c:\outfile.txt"&lt;/span&gt;
  &lt;span class="attr"&gt;traceOutputOptions&lt;/span&gt;&lt;span class="kwrd"&gt;="ProcessId, DateTime, LogicalOperationStack"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;filter&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.EventTypeFilter"&lt;/span&gt;
    &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="Error"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

NOTE: you can have more than one trace source, for example, one for normal data and another for critical and private data.  &lt;br&gt;&lt;br&gt;

By using the shareListeners setting you can add global listeners:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;sharedListeners&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="myListener"&lt;/span&gt; 
    &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.TextWriterTraceListener"&lt;/span&gt; 
    &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="myListener.log"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;filter&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="System.Diagnostics.EventTypeFilter"&lt;/span&gt; 
      &lt;span class="attr"&gt;initializeData&lt;/span&gt;&lt;span class="kwrd"&gt;="Error"&lt;/span&gt;&lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5902810801182247667?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5902810801182247667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5902810801182247667' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5902810801182247667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5902810801182247667'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/about-trace-listeners.html' title='About Trace Listeners'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4263414545769697779</id><published>2008-01-19T19:43:00.000-08:00</published><updated>2008-01-19T20:08:09.674-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>The Debugger and Debug classes</title><content type='html'>Using the debugger is very easy:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;int&lt;/span&gt; x = 0;
&amp;nbsp;
&lt;span class="rem"&gt;// Attach debugger at runtime&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!Debugger.IsAttached)
    Debugger.Launch();
&amp;nbsp;
&lt;span class="rem"&gt;// Logging something&lt;/span&gt;
Debugger.Log(0, &lt;span class="str"&gt;"category 1"&lt;/span&gt;, &lt;span class="str"&gt;"Debugging starts now"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Conditional breakpoint&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (x == 0)
    Debugger.Break();
&lt;/pre&gt;

By using the Debug class we can perform several debugging tasks like make &lt;em&gt;assertions&lt;/em&gt;, write more detailed information about our objects, add a custom trace listener, etc.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Adding a custom listener&lt;/span&gt;
Debug.Listeners.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; TextWriterTraceListener(&lt;span class="str"&gt;"C:\\debug.txt"&lt;/span&gt;));
&amp;nbsp;
&lt;span class="rem"&gt;// Assertions&lt;/span&gt;
Debug.Assert(x == 0, &lt;span class="str"&gt;"x != 0\n"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Printing values&lt;/span&gt;
x = 10;
Debug.Print(&lt;span class="str"&gt;"x value={0}"&lt;/span&gt;, x);
&amp;nbsp;
&lt;span class="rem"&gt;// Writing something to output&lt;/span&gt;
Debug.WriteLine(&lt;span class="str"&gt;"testing message"&lt;/span&gt;);
Debug.WriteLineIf(x == 0, &lt;span class="str"&gt;"x is equal to 0"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Finally, we need to flush data out&lt;/span&gt;
Debug.Flush();
&lt;/pre&gt;

Debug attributes can be used to improve our code readability on debug mode.  

In the following example I use some attributes to hide elements, show collection elements at root, avoid entering to debug internal methods and display a custom formatted attributes when we are debugging some &lt;em&gt;Person&lt;/em&gt; object:

&lt;pre class="csharpcode"&gt;
[DebuggerDisplay(&lt;span class="str"&gt;"Person Name={Name} LastName={LastName} Friends={Friends.Count}"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;class&lt;/span&gt; Person
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName { get; set; }
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Age { get; set; }
&amp;nbsp;
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; _realAge;
&amp;nbsp;
    [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
    &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; Friends = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;() {&lt;span class="str"&gt;"friend 1"&lt;/span&gt;, &lt;span class="str"&gt;"friend 2"&lt;/span&gt;, &lt;span class="str"&gt;"friend 3"&lt;/span&gt;};
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Person()
    {
    }
&amp;nbsp;
    &lt;span class="rem"&gt;// Debugger won't stop in this method&lt;/span&gt;
    [DebuggerStepThrough()]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; BuildFullName()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; Name + &lt;span class="str"&gt;" "&lt;/span&gt; + LastName;
    }
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4263414545769697779?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4263414545769697779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4263414545769697779' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4263414545769697779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4263414545769697779'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/debugger-class.html' title='The Debugger and Debug classes'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-8643839633342929626</id><published>2008-01-19T15:56:00.000-08:00</published><updated>2008-02-09T09:45:45.782-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>The Installer class</title><content type='html'>Creating our custom installer class:

&lt;pre class="csharpcode"&gt;
[RunInstaller(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myCustomInstaller : Installer
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myCustomInstaller()
    {
        &lt;span class="rem"&gt;// Handling some events&lt;/span&gt;
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.BeforeInstall += &lt;span class="kwrd"&gt;new&lt;/span&gt; InstallEventHandler(myCustomInstaller_BeforeInstall);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Committed += &lt;span class="kwrd"&gt;new&lt;/span&gt; InstallEventHandler(myCustomInstaller_Committed);
        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Committing += &lt;span class="kwrd"&gt;new&lt;/span&gt; InstallEventHandler(myCustomInstaller_Committing);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;void&lt;/span&gt; myCustomInstaller_BeforeInstall(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, InstallEventArgs e)
    {
        Console.WriteLine(&lt;span class="str"&gt;"Before installing Event occured."&lt;/span&gt;);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MyInstaller_Committing(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, InstallEventArgs e)
    {
        Console.WriteLine(&lt;span class="str"&gt;"Committing Event occured."&lt;/span&gt;);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MyInstaller_Committed(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, InstallEventArgs e)
    {
        Console.WriteLine(&lt;span class="str"&gt;"Committed Event occured."&lt;/span&gt;);
    }
&amp;nbsp;
    &lt;span class="rem"&gt;// Overriding some methods&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Install(IDictionary stateSaver)
    {
        &lt;span class="kwrd"&gt;base&lt;/span&gt;.Install(stateSaver);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Commit(IDictionary savedState)
    {
        &lt;span class="kwrd"&gt;base&lt;/span&gt;.Commit(savedState);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Rollback(IDictionary savedState)
    {
        &lt;span class="kwrd"&gt;base&lt;/span&gt;.Rollback(savedState);
    }
&amp;nbsp;
}
&lt;/pre&gt;

This class can be used by the &lt;em&gt;InstallUtil.exe&lt;/em&gt; tool or one &lt;em&gt;Setup Project&lt;/em&gt; for our application.&lt;br&gt;&lt;br&gt;

Other installation classes:&lt;br&gt;&lt;br&gt;

&lt;em&gt;AssemblyInstaller&lt;br&gt;
ComponentInstaller&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EventLogInstaller&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PerformanceCounterInstaller&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MessageQueueInstaller&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ServiceInstaller&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ServiceProcessInstaller&lt;br&gt;
ManagedInstaller&lt;br&gt;
InstallerCollection&lt;br&gt;
TransactedInstaller&lt;/em&gt;&lt;br&gt;&lt;br&gt;

More source code at &lt;a href="http://olondono.blogspot.com/2008/01/self-installing-service.html"&gt;Self Installing service.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-8643839633342929626?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/8643839633342929626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=8643839633342929626' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8643839633342929626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/8643839633342929626'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/installer-class.html' title='The Installer class'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2284206357030293045</id><published>2008-01-19T14:16:00.000-08:00</published><updated>2008-02-09T09:46:18.370-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>EventLog management</title><content type='html'>Writing to the Event Log:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Creating the event source&lt;/span&gt;
EventSourceCreationData escd = &lt;span class="kwrd"&gt;new&lt;/span&gt; EventSourceCreationData(&lt;span class="str"&gt;"mySourceName"&lt;/span&gt;, &lt;span class="str"&gt;"myLogName"&lt;/span&gt;);
EventLog.CreateEventSource(escd);
&amp;nbsp;
..
&amp;nbsp;
&lt;span class="rem"&gt;// We can also create the event source directly&lt;/span&gt;
EventLog.CreateEventSource(&lt;span class="str"&gt;"mySourceName"&lt;/span&gt;, &lt;span class="str"&gt;"myLogName"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Opening the event log for writing to it&lt;/span&gt;
EventLog el = &lt;span class="kwrd"&gt;new&lt;/span&gt; EventLog(&lt;span class="str"&gt;"myLogName"&lt;/span&gt;);
el.Source = &lt;span class="str"&gt;"mySourceName"&lt;/span&gt;;
&amp;nbsp;
&lt;span class="rem"&gt;// Writing something&lt;/span&gt;
el.WriteEntry(&lt;span class="str"&gt;"testing message"&lt;/span&gt;, EventLogEntryType.Information);
&amp;nbsp;
&lt;span class="rem"&gt;// Or, writing directly&lt;/span&gt;
EventLog.WriteEntry(&lt;span class="str"&gt;"mySourceName"&lt;/span&gt;, &lt;span class="str"&gt;"direct testing message"&lt;/span&gt;, EventLogEntryType.Information);
&lt;/pre&gt;

&lt;strong&gt;NOTE:&lt;/strong&gt; for writing to one system's log, we can use set the log's name as &lt;em&gt;Application&lt;/em&gt;, &lt;em&gt;System&lt;/em&gt; or &lt;em&gt;Security&lt;/em&gt;.

Deleting logs:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Deleting the source&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (EventLog.SourceExists(&lt;span class="str"&gt;"mySourceName"&lt;/span&gt;))
    EventLog.DeleteEventSource(&lt;span class="str"&gt;"mySourceName"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Deleting the log&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (EventLog.Exists(&lt;span class="str"&gt;"myLogName"&lt;/span&gt;))
    EventLog.Delete(&lt;span class="str"&gt;"myLogName"&lt;/span&gt;);
&lt;/pre&gt;

Reading logs:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Getting all available logs&lt;/span&gt;
EventLog[] els = EventLog.GetEventLogs();
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (EventLog log &lt;span class="kwrd"&gt;in&lt;/span&gt; els)
    MessageBox.Show(&lt;span class="str"&gt;"Log: "&lt;/span&gt; + log.Log + &lt;span class="str"&gt;" - Display Name: "&lt;/span&gt; + log.LogDisplayName);
&amp;nbsp;
&lt;span class="rem"&gt;// Reading all entries from one log&lt;/span&gt;
EventLog el = &lt;span class="kwrd"&gt;new&lt;/span&gt; EventLog(&lt;span class="str"&gt;"Application"&lt;/span&gt;);
&amp;nbsp;
EventLogEntryCollection elec = el.Entries;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (EventLogEntry ele &lt;span class="kwrd"&gt;in&lt;/span&gt; elec)
    MessageBox.Show(ele.Message);
&lt;/pre&gt;

Other classes:&lt;br&gt;&lt;br&gt;

&lt;em&gt;EventLogInstaller&lt;br&gt;
EventLogPermission&lt;br&gt;
EventLogPermissionAttribute&lt;br&gt;
EventLogTraceListener&lt;br&gt;
EventLogEntry&lt;/em&gt;&lt;br&gt;&lt;br&gt;

More information &lt;a href="http://msdn2.microsoft.com/en-us/library/system.diagnostics.eventlog.aspx"&gt;MSDN&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2284206357030293045?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2284206357030293045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2284206357030293045' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2284206357030293045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2284206357030293045'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/eventlog-management.html' title='EventLog management'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-3204221493314659060</id><published>2008-01-09T14:18:00.000-08:00</published><updated>2008-02-09T09:46:40.886-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><title type='text'>Error installing Visual Studio Express 2008 (C#)</title><content type='html'>I had errors installing VS 2008 Express (C#), when I reviewed log files, I found the error description: &lt;em&gt;&lt;span style="color:#990000;"&gt;"Error: Installation failed for component Microsoft .NET Framework 2.0a. MSI returned error code 1603"&lt;/span&gt;&lt;/em&gt;&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

I tried to uninstall the .NET Framework 2.0 Service Pack 1, but none results.  So, I used the &lt;em&gt;"Windows Install Clean Up"&lt;/em&gt; utility to remove the .NET Framework 2.0 Service Pack 1.  The installer ran well after that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3204221493314659060?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3204221493314659060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3204221493314659060' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3204221493314659060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3204221493314659060'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/error-installing-visual-studio-express.html' title='Error installing Visual Studio Express 2008 (C#)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-2024251829902820525</id><published>2008-01-08T12:19:00.000-08:00</published><updated>2008-01-08T14:11:19.655-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Conversion between ANSI and Unicode</title><content type='html'>We can read ANSI files using the system's current ANSI code page:

&lt;pre class="csharpcode"&gt;
StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(&lt;span class="str"&gt;"C:\\filename.txt"&lt;/span&gt;, Encoding.Default);
&lt;span class="kwrd"&gt;string&lt;/span&gt; str = sr.ReadToEnd();
sr.Close();
&lt;/pre&gt;

We can select one custom code page by using the &lt;em&gt;GetEncoding&lt;/em&gt; method:

&lt;pre class="csharpcode"&gt;
StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(&lt;span class="str"&gt;"C:\\filename.txt"&lt;/span&gt;, Encoding.GetEncoding(1252));
&lt;span class="kwrd"&gt;string&lt;/span&gt; str = sr.ReadToEnd();
sr.Close();
&lt;/pre&gt;

In the similar way we can convert from Unicode to ANSI using Default encoding or a custom code page:

&lt;pre class="csharpcode"&gt;
StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(&lt;span class="str"&gt;"C:\\filename.txt"&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;, Encoding.Default);
sw.Write(str);
sw.Close();
&lt;/pre&gt;

&lt;pre class="csharpcode"&gt;
StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(&lt;span class="str"&gt;"C:\\filename.txt"&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;, Encoding.GetEncoding(1252));
sw.Write(str);
sw.Close();
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-2024251829902820525?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/2024251829902820525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=2024251829902820525' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2024251829902820525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/2024251829902820525'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/conversion-between-ansi-and-unicode.html' title='Conversion between ANSI and Unicode'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-1756728844877061829</id><published>2008-01-07T15:12:00.000-08:00</published><updated>2008-02-09T09:48:48.448-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Advanced .NET Configuration techniques</title><content type='html'>We can create custom configuration sections:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myConfigurationSection : ConfigurationSection
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myConfigurationSection()
    {
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"validateActions"&lt;/span&gt;, IsRequired = &lt;span class="kwrd"&gt;false&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; ValidateActions
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;bool&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"validateActions"&lt;/span&gt;]; }
        set { &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"validateActions"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
&amp;nbsp;    
    [ConfigurationProperty(&lt;span class="str"&gt;"users"&lt;/span&gt;, IsRequired=&lt;span class="kwrd"&gt;false&lt;/span&gt;, IsDefaultCollection=&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myUsersCollection Users
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (myUsersCollection) &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"users"&lt;/span&gt;]; }
    }
}
&lt;/pre&gt;

Using our configuration section:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the configuration&lt;/span&gt;
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
&amp;nbsp;       
&lt;span class="rem"&gt;// Reading our configuration section&lt;/span&gt;
myConfigurationSection mcs = config.Sections[&lt;span class="str"&gt;"myConfiguration"&lt;/span&gt;] &lt;span class="kwrd"&gt;as&lt;/span&gt; myConfigurationSection;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (mcs == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    &lt;span class="rem"&gt;// Create the configuration section if it doesn't exist&lt;/span&gt;
    mcs = &lt;span class="kwrd"&gt;new&lt;/span&gt; myConfigurationSection();
    config.Sections.Add(&lt;span class="str"&gt;"myConfiguration"&lt;/span&gt;, mcs);
}
&amp;nbsp;
&lt;span class="rem"&gt;// Add some users&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (mcs.Users[&lt;span class="str"&gt;"john"&lt;/span&gt;] == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    mcs.Users.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; myUserElement(&lt;span class="str"&gt;"john"&lt;/span&gt;, &lt;span class="str"&gt;"pass"&lt;/span&gt;));
&lt;span class="kwrd"&gt;if&lt;/span&gt; (mcs.Users[&lt;span class="str"&gt;"mary"&lt;/span&gt;] == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    mcs.Users.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; myUserElement(&lt;span class="str"&gt;"mary"&lt;/span&gt;, &lt;span class="str"&gt;"pass"&lt;/span&gt;));
&amp;nbsp;
&lt;span class="rem"&gt;// Save the configuration&lt;/span&gt;
config.Save(ConfigurationSaveMode.Modified);
&lt;/pre&gt;

The example above will produce the following result:&lt;br&gt;&lt;br&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="myConfiguration"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="WindowsFormsApplication1.myConfigurationSection, WindowsFormsApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&amp;nbsp;
...
&amp;nbsp;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;users&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="john"&lt;/span&gt; &lt;span class="attr"&gt;pwd&lt;/span&gt;&lt;span class="kwrd"&gt;="pass"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="mary"&lt;/span&gt; &lt;span class="attr"&gt;pwd&lt;/span&gt;&lt;span class="kwrd"&gt;="pass"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;users&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;
...&lt;/pre&gt;

&lt;strong&gt;Some points of interest:&lt;/strong&gt; &lt;br&gt;&lt;br&gt;

- We can use the configuration property attribute to set some constraints and preferences with values, like &lt;em&gt;IsRequired&lt;/em&gt; by example: &lt;em&gt;[ConfigurationProperty("validateActions", IsRequired = false)]&lt;/em&gt;&lt;br&gt;&lt;br&gt;

- If we don't want to use the named collection property ("users" in this example), we need to change the Users property to include the &lt;em&gt;IsDefaultCollection&lt;/em&gt; property and set the property's name to an empty string:&lt;br&gt;&lt;br&gt;

&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;pre class="csharpcode"&gt;
[ConfigurationProperty(&lt;span class="str"&gt;""&lt;/span&gt;, IsRequired=&lt;span class="kwrd"&gt;false&lt;/span&gt;, IsDefaultCollection=&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; myUsersCollection Users
{
    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (myUsersCollection) &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;""&lt;/span&gt;]; }
}
&lt;/pre&gt;

This will produce the following result:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="myConfiguration"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="WindowsFormsApplication1.myConfigurationSection, WindowsFormsApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
&amp;nbsp;
...
&amp;nbsp;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="john"&lt;/span&gt; &lt;span class="attr"&gt;pwd&lt;/span&gt;&lt;span class="kwrd"&gt;="pass"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="mary"&lt;/span&gt; &lt;span class="attr"&gt;pwd&lt;/span&gt;&lt;span class="kwrd"&gt;="pass"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myConfiguration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;
...
&lt;/pre&gt;

Here is myUserElement declaration:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myUserElement: ConfigurationElement
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myUserElement()
    {
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myUserElement(&lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;string&lt;/span&gt; pwd)
    {
        Name = name;
        Pwd = pwd;
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"name"&lt;/span&gt;, IsRequired = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"name"&lt;/span&gt;]; }
        set { &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"name"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"pwd"&lt;/span&gt;, IsRequired = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Pwd
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"pwd"&lt;/span&gt;]; }
        set { &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"pwd"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"lastVisit"&lt;/span&gt;, IsRequired = &lt;span class="kwrd"&gt;false&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastVisit
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"lastVisit"&lt;/span&gt;]; }
        set { &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"lastVisit"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"permissions"&lt;/span&gt;, IsRequired = &lt;span class="kwrd"&gt;false&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myPermissionsCollection Permissions
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (myPermissionsCollection)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"permissions"&lt;/span&gt;]; }
    }
}
&lt;/pre&gt;

&lt;strong&gt;Configuration Element collection&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

I need to create a class from &lt;em&gt;ConfigurationElementCollection&lt;/em&gt; and override the &lt;em&gt;CreateNewElement&lt;/em&gt; and the &lt;em&gt;GetElementKey&lt;/em&gt; methods.  Also, I have to implement some helper methods like &lt;em&gt;Add&lt;/em&gt;, &lt;em&gt;Remove&lt;/em&gt;, the &lt;em&gt;indexer []&lt;/em&gt;, etc.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[ConfigurationCollection(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(myUserElement), 
    CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myUsersCollection: ConfigurationElementCollection
{
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ConfigurationElement CreateNewElement()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; myUserElement();
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; GetElementKey(ConfigurationElement element)
    {
        myUserElement melement = element &lt;span class="kwrd"&gt;as&lt;/span&gt; myUserElement;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; melement.Name;
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myUserElement &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="kwrd"&gt;int&lt;/span&gt; index]
    {
        get
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; (myUserElement)BaseGet(index);
        }
        set
        {
            &lt;span class="rem"&gt;// If it exists, remove first, then add&lt;/span&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (BaseGet(index) != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                BaseRemoveAt(index);
&amp;nbsp;
            BaseAdd(index, &lt;span class="kwrd"&gt;value&lt;/span&gt;);
        }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; myUserElement &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="kwrd"&gt;string&lt;/span&gt; Name]
    {
        get
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; (myUserElement)BaseGet(Name);
        }
        set
        {
            &lt;span class="rem"&gt;// If it exists, remove first, then add&lt;/span&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (BaseGet(Name) != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                BaseRemove(Name);
&amp;nbsp;
            BaseAdd(&lt;span class="kwrd"&gt;value&lt;/span&gt;);
        }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(myUserElement element)
    {
        BaseAdd(element);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(&lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;string&lt;/span&gt; pwd)
    {
        myUserElement element = &lt;span class="kwrd"&gt;new&lt;/span&gt; myUserElement(name, pwd);
&amp;nbsp;
        BaseAdd(element);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(myUserElement element)
    {
        Remove(element.Name);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;string&lt;/span&gt; name)
    {
        BaseRemove(name);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RemoveAt(&lt;span class="kwrd"&gt;int&lt;/span&gt; index)
    {
        BaseRemoveAt(index);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; IndexOf(myUserElement element)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; BaseIndexOf(element);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Clear()
    {
        BaseClear();
    }
}
&lt;/pre&gt;

The &lt;em&gt;CollectionType&lt;/em&gt; property indicates how we want to map this collection, by default the &lt;em&gt;AddRemoveClearMap&lt;/em&gt; is used.  It says that the &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;add.../&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; element is expected, and also, the &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;clear&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; element can be used to avoid inherite configuration values from the configuration file parent.  We can change the &lt;add&gt; element by a custom one simply adding the &lt;em&gt;AddItemName="newAddName"&lt;/em&gt; attribute to the collection declaration.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[ConfigurationCollection(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(myUserElement),
    AddItemName="myAdd", 
    CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myUsersCollection: ConfigurationElementCollection
{
...
}
&lt;/pre&gt;

Here is our &lt;em&gt;Permission&lt;/em&gt; element and the collection declaration:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myPermissionElement: ConfigurationElement
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myPermissionElement()
    {
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myPermissionElement(&lt;span class="kwrd"&gt;string&lt;/span&gt; action, &lt;span class="kwrd"&gt;string&lt;/span&gt; acl)
    {
        Action = action;
        Acl = acl;
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"action"&lt;/span&gt;, IsKey=&lt;span class="kwrd"&gt;true&lt;/span&gt;, IsRequired=&lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Action
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"action"&lt;/span&gt;]; }
        set { &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"action"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"acl"&lt;/span&gt;, IsRequired=&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Acl
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"acl"&lt;/span&gt;]; }
        set { &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"acl"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
}
&amp;nbsp;
[ConfigurationCollection(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(myPermissionElement), 
    CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myPermissionsCollection: ConfigurationElementCollection
{
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ConfigurationElement CreateNewElement()
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; myPermissionElement();
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; GetElementKey(ConfigurationElement element)
    {
        myPermissionElement melement = element &lt;span class="kwrd"&gt;as&lt;/span&gt; myPermissionElement;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; melement.Action;
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myPermissionElement &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="kwrd"&gt;int&lt;/span&gt; index]
    {
        get
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; (myPermissionElement)BaseGet(index);
        }
        set
        {
            &lt;span class="rem"&gt;// If it exists, remove first, then add&lt;/span&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (BaseGet(index) != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                BaseRemoveAt(index);
&amp;nbsp;
            BaseAdd(index, &lt;span class="kwrd"&gt;value&lt;/span&gt;);
        }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; myPermissionElement &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="kwrd"&gt;string&lt;/span&gt; Name]
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (myPermissionElement)BaseGet(Name); }
        set
        {
            &lt;span class="rem"&gt;// If it exists, remove first, then add&lt;/span&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (BaseGet(Name) != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
                BaseRemove(Name);
&amp;nbsp;
            BaseAdd(&lt;span class="kwrd"&gt;value&lt;/span&gt;);
        }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(myPermissionElement element)
    {
        BaseAdd(element);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(&lt;span class="kwrd"&gt;string&lt;/span&gt; action, &lt;span class="kwrd"&gt;string&lt;/span&gt; acl)
    {
        myPermissionElement element = &lt;span class="kwrd"&gt;new&lt;/span&gt; myPermissionElement(action, acl);
&amp;nbsp;
        BaseAdd(element);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Add(myUserElement element)
    {
        BaseAdd(element);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;string&lt;/span&gt; name)
    {
        BaseRemove(name);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RemoveAt(&lt;span class="kwrd"&gt;int&lt;/span&gt; index)
    {
        BaseRemoveAt(index);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; IndexOf(myUserElement element)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; BaseIndexOf(element);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Clear()
    {
        BaseClear();
    }
}
&lt;/pre&gt;

&lt;strong&gt;Configuration validator&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

We can use one of the standards validator classes like &lt;em&gt;IntegerValidator&lt;/em&gt;, &lt;em&gt;TimeSpanValidator&lt;/em&gt;, &lt;em&gt;StringValidator&lt;/em&gt;, &lt;em&gt;RegexStringValidator&lt;/em&gt;, etc. &lt;br&gt;&lt;br&gt;

If we want to create a custom validator for our configuration elements, we need to implement a class from the &lt;em&gt;ConfigurationValidatorBase&lt;/em&gt; or use the &lt;em&gt;CallbackValidator&lt;/em&gt; attribute with our callback delegate method &lt;em&gt;[CallbackValidator("myDelegateMethod")]&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myCustomValidator: ConfigurationValidatorBase
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Validate(&lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;)
    {
        &lt;span class="kwrd"&gt;switch&lt;/span&gt; ((&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;value&lt;/span&gt;)
        {
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"add"&lt;/span&gt;:
                &lt;span class="kwrd"&gt;break&lt;/span&gt;;
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"remove"&lt;/span&gt;:
                &lt;span class="kwrd"&gt;break&lt;/span&gt;;
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"edit"&lt;/span&gt;:
                &lt;span class="kwrd"&gt;break&lt;/span&gt;;
            &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;""&lt;/span&gt;:
                &lt;span class="kwrd"&gt;break&lt;/span&gt;;
            &lt;span class="kwrd"&gt;default&lt;/span&gt;:
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentOutOfRangeException(&lt;span class="str"&gt;"Invalid Action name: "&lt;/span&gt; + (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;value&lt;/span&gt;);
        }
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; CanValidate(Type type)
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (type == &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;))
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;
&amp;nbsp;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }
}
&lt;/pre&gt;

Using our validator:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[ConfigurationProperty(&lt;span class="str"&gt;"action"&lt;/span&gt;, IsKey=&lt;span class="kwrd"&gt;true&lt;/span&gt;, IsRequired=&lt;span class="kwrd"&gt;true&lt;/span&gt;),
ConfigurationValidator(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(myCustomValidator))]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Action
{
    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"action"&lt;/span&gt;]; }
    set { &lt;span class="kwrd"&gt;this&lt;/span&gt;[&lt;span class="str"&gt;"action"&lt;/span&gt;] = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
}
&lt;/pre&gt;

The &lt;em&gt;ConfigurationValidatorAttribute&lt;/em&gt; can be implemented for exposing the validator attribute with custom parameters, such as, initial values, ranges or constraints.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Configuration Section Groups&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

They can be implemented for managing custom section groups, example:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; myConfigurationGroup: ConfigurationSectionGroup
{
    [ConfigurationProperty(&lt;span class="str"&gt;"myConfigSec"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; myConfigurationSection myConfigSec
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (myConfigurationSection)&lt;span class="kwrd"&gt;base&lt;/span&gt;.Sections[&lt;span class="str"&gt;"myConfigSec"&lt;/span&gt;]; }
    }
&amp;nbsp;
    [ConfigurationProperty(&lt;span class="str"&gt;"anotherSec"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; anotherCustomConfigSection anotherSec
    {
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (anotherCustomConfigSection)&lt;span class="kwrd"&gt;base&lt;/span&gt;.Sections[&lt;span class="str"&gt;"anotherSec"&lt;/span&gt;]; }
    }
}
&amp;nbsp;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; anotherCustomConfigSection: ConfigurationSection
{
}
&lt;/pre&gt;

Using configuration groups:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the configuration&lt;/span&gt;
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
&amp;nbsp;
&lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Reading our configuration group section&lt;/span&gt;
myConfigurationGroup cg = config.SectionGroups[&lt;span class="str"&gt;"myConfigGroup"&lt;/span&gt;] &lt;span class="kwrd"&gt;as&lt;/span&gt; myConfigurationGroup;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (cg == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    &lt;span class="rem"&gt;// Create the configuration group section if it doesn't exist&lt;/span&gt;
    cg = &lt;span class="kwrd"&gt;new&lt;/span&gt; myConfigurationGroup();
    config.SectionGroups.Add(&lt;span class="str"&gt;"myConfigGroup"&lt;/span&gt;, cg);
}
&lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Reading our configuration section inside the group section&lt;/span&gt;
myConfigurationSection mcs = cg.myConfigSec;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (mcs == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    &lt;span class="rem"&gt;// Create the configuration section if it doesn't exist&lt;/span&gt;
    mcs = &lt;span class="kwrd"&gt;new&lt;/span&gt; myConfigurationSection();
    cg.Sections.Add(&lt;span class="str"&gt;"myconfig"&lt;/span&gt;, mcs);
}
&lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Adding some users&lt;/span&gt;
myUserElement ue = mcs.Users[&lt;span class="str"&gt;"john"&lt;/span&gt;];
&lt;span class="kwrd"&gt;if&lt;/span&gt; (ue == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    ue = &lt;span class="kwrd"&gt;new&lt;/span&gt; myUserElement(&lt;span class="str"&gt;"john"&lt;/span&gt;, &lt;span class="str"&gt;"pass"&lt;/span&gt;);
    mcs.Users.Add(ue);
}
&amp;nbsp;
ue.Permissions.Add(&lt;span class="str"&gt;"add"&lt;/span&gt;, &lt;span class="str"&gt;"grant"&lt;/span&gt;);
ue.Permissions.Add(&lt;span class="str"&gt;"edit"&lt;/span&gt;, &lt;span class="str"&gt;"grant"&lt;/span&gt;);
ue.Permissions.Add(&lt;span class="str"&gt;"remove"&lt;/span&gt;, &lt;span class="str"&gt;"denied"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Adding another user&lt;/span&gt;
ue = mcs.Users[&lt;span class="str"&gt;"mary"&lt;/span&gt;];
&lt;span class="kwrd"&gt;if&lt;/span&gt; (ue == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    ue = &lt;span class="kwrd"&gt;new&lt;/span&gt; myUserElement(&lt;span class="str"&gt;"mary"&lt;/span&gt;, &lt;span class="str"&gt;"pass"&lt;/span&gt;);
    mcs.Users.Add(ue);
}
&amp;nbsp;
ue.Permissions.Add(&lt;span class="str"&gt;"add"&lt;/span&gt;, &lt;span class="str"&gt;"grant"&lt;/span&gt;);
ue.Permissions.Add(&lt;span class="str"&gt;"edit"&lt;/span&gt;, &lt;span class="str"&gt;"grant"&lt;/span&gt;);
ue.Permissions.Add(&lt;span class="str"&gt;"remove"&lt;/span&gt;, &lt;span class="str"&gt;"grant"&lt;/span&gt;);
&lt;span class="rem"&gt;//-----------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;// Saving the configuration&lt;/span&gt;
config.Save(ConfigurationSaveMode.Modified);
&lt;/pre&gt;

This will produce the following result:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="utf-8"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;
...
&amp;nbsp;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;sectionGroup&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="myConfigGroup"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="WindowsFormsApplication1.myConfigurationGroup, WindowsFormsApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&lt;/span&gt; &lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;section&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="myconfig"&lt;/span&gt; &lt;span class="attr"&gt;type&lt;/span&gt;&lt;span class="kwrd"&gt;="WindowsFormsApplication1.myConfigurationSection, WindowsFormsApplication3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;sectionGroup&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configSections&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&amp;nbsp;
...
&amp;nbsp;
  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myConfigGroup&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;myconfig&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="john"&lt;/span&gt; &lt;span class="attr"&gt;pwd&lt;/span&gt;&lt;span class="kwrd"&gt;="pass"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;permissions&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;action&lt;/span&gt;&lt;span class="kwrd"&gt;="add"&lt;/span&gt; &lt;span class="attr"&gt;acl&lt;/span&gt;&lt;span class="kwrd"&gt;="grant"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;action&lt;/span&gt;&lt;span class="kwrd"&gt;="edit"&lt;/span&gt; &lt;span class="attr"&gt;acl&lt;/span&gt;&lt;span class="kwrd"&gt;="grant"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;action&lt;/span&gt;&lt;span class="kwrd"&gt;="remove"&lt;/span&gt; &lt;span class="attr"&gt;acl&lt;/span&gt;&lt;span class="kwrd"&gt;="denied"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;permissions&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;="mary"&lt;/span&gt; &lt;span class="attr"&gt;pwd&lt;/span&gt;&lt;span class="kwrd"&gt;="pass"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;permissions&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;action&lt;/span&gt;&lt;span class="kwrd"&gt;="add"&lt;/span&gt; &lt;span class="attr"&gt;acl&lt;/span&gt;&lt;span class="kwrd"&gt;="grant"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;action&lt;/span&gt;&lt;span class="kwrd"&gt;="edit"&lt;/span&gt; &lt;span class="attr"&gt;acl&lt;/span&gt;&lt;span class="kwrd"&gt;="grant"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;action&lt;/span&gt;&lt;span class="kwrd"&gt;="remove"&lt;/span&gt; &lt;span class="attr"&gt;acl&lt;/span&gt;&lt;span class="kwrd"&gt;="grant"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;permissions&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myconfig&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;myConfigGroup&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-1756728844877061829?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/1756728844877061829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=1756728844877061829' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1756728844877061829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/1756728844877061829'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/advanced-net-configuration-techniques.html' title='Advanced .NET Configuration techniques'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-760938554100670628</id><published>2008-01-07T08:16:00.000-08:00</published><updated>2008-02-09T09:49:48.611-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>The .NET Configuration (app.config)</title><content type='html'>The easiest way to read and write to the app.config file is using the &lt;em&gt;AppSettings&lt;/em&gt;:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the app.config file (from this executable)&lt;/span&gt;
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
&amp;nbsp;
&lt;span class="rem"&gt;// Reading our setting (both are the same but the first is preferred)&lt;/span&gt;
MessageBox.Show(ConfigurationManager.AppSettings[&lt;span class="str"&gt;"mySetting1"&lt;/span&gt;]);
MessageBox.Show(config.AppSettings.Settings[&lt;span class="str"&gt;"mySetting1"&lt;/span&gt;].Value);
&amp;nbsp;
&lt;span class="rem"&gt;// Writing some setting&lt;/span&gt;
config.AppSettings.Settings.Add(&lt;span class="str"&gt;"mySetting2"&lt;/span&gt;, &lt;span class="str"&gt;"myValue2"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Saving the file&lt;/span&gt;
config.Save(ConfigurationSaveMode.Modified);
&amp;nbsp;
&lt;span class="rem"&gt;// Reloading the modified section&lt;/span&gt;
ConfigurationManager.RefreshSection(&lt;span class="str"&gt;"appSettings"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Reading again&lt;/span&gt;
MessageBox.Show(ConfigurationManager.AppSettings[&lt;span class="str"&gt;"mySetting2"&lt;/span&gt;]);
MessageBox.Show(config.AppSettings.Settings[&lt;span class="str"&gt;"mySetting2"&lt;/span&gt;].Value);
&lt;/pre&gt;

Reading and writing connection strings:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Reading all connection strings&lt;/span&gt;
ConnectionStringSettingsCollection csCol = ConfigurationManager.ConnectionStrings;
&amp;nbsp;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (csCol != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
{
    StringBuilder sb = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();
    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (ConnectionStringSettings cs &lt;span class="kwrd"&gt;in&lt;/span&gt; csCol)
    {
        sb.Append(&lt;span class="str"&gt;"Full Connection String: "&lt;/span&gt; + cs.ConnectionString + &lt;span class="str"&gt;"\r\n"&lt;/span&gt;);
        sb.Append(&lt;span class="str"&gt;"Provider Name: "&lt;/span&gt; + cs.ProviderName + &lt;span class="str"&gt;"\r\n"&lt;/span&gt;);
        sb.Append(&lt;span class="str"&gt;"Section Name: "&lt;/span&gt; + cs.Name + &lt;span class="str"&gt;"\r\n"&lt;/span&gt;);
    }
&amp;nbsp;
    MessageBox.Show(sb.ToString());
}
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Reading only one connection string by name&lt;/span&gt;
ConnectionStringSettings csOracle = ConfigurationManager.ConnectionStrings[&lt;span class="str"&gt;"OracleConnectionString"&lt;/span&gt;];
&amp;nbsp;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (csOracle != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    MessageBox.Show(csOracle.ConnectionString);
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Reading the default database connection with&lt;/span&gt;
&lt;span class="rem"&gt;// the Enterprise Library Data Access Application Block&lt;/span&gt;
DatabaseSettings ds = ConfigurationManager.GetSection(&lt;span class="str"&gt;"dataConfiguration"&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; DatabaseSettings;
&amp;nbsp;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (ds != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    MessageBox.Show(ds.DefaultDatabase);
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&amp;nbsp;
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&lt;span class="rem"&gt;// Creating a new connection string&lt;/span&gt;
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
&amp;nbsp;
ConnectionStringsSection csSection = config.ConnectionStrings;
&amp;nbsp;
csSection.ConnectionStrings.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; ConnectionStringSettings(&lt;span class="str"&gt;"myNewConnection"&lt;/span&gt;, &lt;span class="str"&gt;"Data Source=localhost;Initial Catalog=AdventureWorks; Integrated Security=true"&lt;/span&gt;, &lt;span class="str"&gt;"System.Data.SqlClient"&lt;/span&gt;));
&amp;nbsp;
config.Save(ConfigurationSaveMode.Modified);
&lt;span class="rem"&gt;//---------------------------------------&lt;/span&gt;
&lt;/pre&gt;

&lt;strong&gt;Protecting sensitive data by encrypting configuration sections&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

We can use the &lt;em&gt;"RsaProtectedConfigurationProvider"&lt;/em&gt; or the &lt;em&gt;"DataProtectionConfigurationProvider/DpapiProtectedConfigurationProvider"&lt;/em&gt; to protect or unprotect our configuration sections:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Open the configuration&lt;/span&gt;
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
&amp;nbsp;
&lt;span class="rem"&gt;// Get the connection strings section&lt;/span&gt;
ConnectionStringsSection csSection = config.ConnectionStrings;
&amp;nbsp;
&lt;span class="rem"&gt;// Protect this section by using the DpapiProtectedConfigurationProvider a.k.a. DataProtectionConfigurationProvider&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!csSection.SectionInformation.IsProtected)
    csSection.SectionInformation.ProtectSection(&lt;span class="str"&gt;"DataProtectionConfigurationProvider"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Save the configuration section within protected data&lt;/span&gt;
csSection.SectionInformation.ForceSave = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
config.Save();
&lt;/pre&gt;

For unprotect sections, we use the &lt;em&gt;UnprotectSection()&lt;/em&gt; method.&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-760938554100670628?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/760938554100670628/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=760938554100670628' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/760938554100670628'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/760938554100670628'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/net-configuration-appconfig.html' title='The .NET Configuration (app.config)'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5880222687561714291</id><published>2008-01-06T08:05:00.001-08:00</published><updated>2008-01-06T12:59:12.709-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Self installing service</title><content type='html'>To make a self installing service, we need to change the Main function into the Program.cs file to look like this:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// The main entry point for the application.&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
{
    &lt;span class="rem"&gt;// Reading command line options&lt;/span&gt;
    &lt;span class="kwrd"&gt;string&lt;/span&gt; opt = &lt;span class="str"&gt;""&lt;/span&gt;;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (args.Length &amp;gt; 0)
        opt = args[0];
&amp;nbsp;
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (opt.ToLower() == &lt;span class="str"&gt;"/install"&lt;/span&gt;)
    {
        TransactedInstaller ti = &lt;span class="kwrd"&gt;new&lt;/span&gt; TransactedInstaller();
        ProjectInstaller pi = &lt;span class="kwrd"&gt;new&lt;/span&gt; ProjectInstaller();
        ti.Installers.Add(pi);
&amp;nbsp;
        &lt;span class="kwrd"&gt;string&lt;/span&gt; path = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"/assemblypath={0}"&lt;/span&gt;,
            System.Reflection.Assembly.GetExecutingAssembly().Location);
&amp;nbsp;
        &lt;span class="kwrd"&gt;string&lt;/span&gt;[] cmdline = { path };
        InstallContext ctx = &lt;span class="kwrd"&gt;new&lt;/span&gt; InstallContext(&lt;span class="str"&gt;""&lt;/span&gt;, cmdline);
        ti.Context = ctx;
        ti.Install(&lt;span class="kwrd"&gt;new&lt;/span&gt; Hashtable());
&amp;nbsp;
        MessageBox.Show(&lt;span class="str"&gt;"Service was successfully installed"&lt;/span&gt;, &lt;span class="str"&gt;"My Service"&lt;/span&gt;, 
            MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (opt.ToLower() == &lt;span class="str"&gt;"/uninstall"&lt;/span&gt;)
    {
        TransactedInstaller ti = &lt;span class="kwrd"&gt;new&lt;/span&gt; TransactedInstaller();
        ProjectInstaller pi = &lt;span class="kwrd"&gt;new&lt;/span&gt; ProjectInstaller();
        ti.Installers.Add(pi);
&amp;nbsp;
        &lt;span class="kwrd"&gt;string&lt;/span&gt; path = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"/assemblypath={0}"&lt;/span&gt;,
            System.Reflection.Assembly.GetExecutingAssembly().Location);
&amp;nbsp;
        &lt;span class="kwrd"&gt;string&lt;/span&gt;[] cmdline = { path };
        InstallContext ctx = &lt;span class="kwrd"&gt;new&lt;/span&gt; InstallContext(&lt;span class="str"&gt;""&lt;/span&gt;, cmdline);
        ti.Context = ctx;
        ti.Uninstall(&lt;span class="kwrd"&gt;null&lt;/span&gt;);
&amp;nbsp;
        MessageBox.Show(&lt;span class="str"&gt;"Service was successfully uninstalled"&lt;/span&gt;, &lt;span class="str"&gt;"My Service"&lt;/span&gt;,
            MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (opt != &lt;span class="str"&gt;""&lt;/span&gt;)
    {
        &lt;span class="rem"&gt;// Attach to debugger at runtime&lt;/span&gt;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!System.Diagnostics.Debugger.IsAttached)
            System.Diagnostics.Debugger.Launch();
&amp;nbsp;
        &lt;span class="rem"&gt;// ignore it&lt;/span&gt;
        MessageBox.Show(&lt;span class="str"&gt;"Invalid option !!!"&lt;/span&gt;, &lt;span class="str"&gt;"My Service"&lt;/span&gt;,
            MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
    {
        ServiceBase[] ServicesToRun;
&amp;nbsp;
        &lt;span class="rem"&gt;// More than one user Service may run within the same process. To add&lt;/span&gt;
        &lt;span class="rem"&gt;// another service to this process, change the following line to&lt;/span&gt;
        &lt;span class="rem"&gt;// create a second service object. For example,&lt;/span&gt;
        &lt;span class="rem"&gt;//&lt;/span&gt;
        &lt;span class="rem"&gt;//   ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};&lt;/span&gt;
        &lt;span class="rem"&gt;//&lt;/span&gt;
        ServicesToRun = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceBase[] { &lt;span class="kwrd"&gt;new&lt;/span&gt; Service1() };
&amp;nbsp;
        ServiceBase.Run(ServicesToRun);
    }            
}
&lt;/pre&gt;

Remember to add references and using statements to:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Configuration.Install;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections;
&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Windows.Forms;
&lt;/pre&gt;

More information &lt;a href="http://pluralsight.com/wiki/default.aspx/Craig.SelfInstallingService"&gt;Self Installing Service [Craig Andera]&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5880222687561714291?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5880222687561714291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5880222687561714291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5880222687561714291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5880222687561714291'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/self-installing-service.html' title='Self installing service'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4724271578573205820</id><published>2008-01-06T07:48:00.000-08:00</published><updated>2008-02-09T09:50:45.833-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Creating Windows Services</title><content type='html'>Today is very easy to create Windows Services with Visual Studio 2005/2008.  Simply, create a new Windows Service project, implement OnStart/OnStop methods and create the service's installer... voila!... you got your Windows Service.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Service1 : ServiceBase
{
    &lt;span class="rem"&gt;// A simple timer&lt;/span&gt;
    Timer myTimer;
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; Service1()
    {
        InitializeComponent();
&amp;nbsp;
        &lt;span class="rem"&gt;// Initialize my timer&lt;/span&gt;
        myTimer = &lt;span class="kwrd"&gt;new&lt;/span&gt; Timer(10000);
        myTimer.Enabled = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
        myTimer.Elapsed += &lt;span class="kwrd"&gt;new&lt;/span&gt; ElapsedEventHandler(myTimer_Elapsed);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;void&lt;/span&gt; myTimer_Elapsed(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, ElapsedEventArgs e)
    {
        &lt;span class="rem"&gt;// Write to the Event Log is very easy, like this&lt;/span&gt;
        EventLog.WriteEntry(&lt;span class="kwrd"&gt;this&lt;/span&gt;.ServiceName, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Timer elapsed at {0}"&lt;/span&gt;, DateTime.Now.ToShortTimeString()), EventLogEntryType.Information);
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnStart(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)
    {
        &lt;span class="rem"&gt;// OnStart: with start the timer to perform &lt;/span&gt;
        &lt;span class="rem"&gt;// some timed task.  Also, we can start threads,&lt;/span&gt;
        &lt;span class="rem"&gt;// subscribe to object's events, etc.&lt;/span&gt;
        myTimer.Enabled = &lt;span class="kwrd"&gt;true&lt;/span&gt;;
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnStop()
    {
        &lt;span class="rem"&gt;// OnStop: we stop the timer or the thread,&lt;/span&gt;
        &lt;span class="rem"&gt;// and we can also release some resources&lt;/span&gt;
        myTimer.Enabled = &lt;span class="kwrd"&gt;false&lt;/span&gt;;
    }
}
&lt;/pre&gt;

In the designer, we can specify properties that tell to the service manager if we want to handle other events and actions like Power event, Session Changed event, Pause and Resume, etc.&lt;br&gt;&lt;br&gt;

To add an installer to our windows service, simply make right click over the Service Designer and choose the option from the popup menu: &lt;em&gt;"Add Installer"&lt;/em&gt;.  This, will create a class like this:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
[RunInstaller(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ProjectInstaller : Installer
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ProjectInstaller()
    {
        InitializeComponent();
    }
}
&lt;/pre&gt;

We can specify in the installer's properties, the account for run our service and the display name, etc.&lt;br&gt;&lt;br&gt;

See my other post for &lt;a href="http://olondono.blogspot.com/2008/01/self-installing-service.html"&gt;Self Installing service&lt;/a&gt;.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4724271578573205820?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4724271578573205820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4724271578573205820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4724271578573205820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4724271578573205820'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/creating-windows-services.html' title='Creating Windows Services'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4231643041612741920</id><published>2008-01-06T07:41:00.000-08:00</published><updated>2008-02-09T09:51:15.858-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KB'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Source Code'/><title type='text'>Attach the Visual Studio Debugger at runtime</title><content type='html'>I have been working in an HTML page that needs to launch an external application (the executable file) and pass it arguments in the command line.  Also, I have been created a Windows Service that I need to debug in some line of source code.&lt;br&gt;&lt;br&gt;
 
How to debug this application or the Windows Service ?&lt;br&gt;&lt;br&gt;
 
&lt;strong&gt;Solution:&lt;/strong&gt; Call the &lt;em&gt;Debugger.Launch()&lt;/em&gt; method before the first line you wish to start debugging the project, like this:&lt;br&gt;&lt;br&gt;
 
&lt;pre class="csharpcode"&gt;
...
&lt;span class="preproc"&gt;#if&lt;/span&gt; DEBUG 
&amp;nbsp;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (!System.Diagnostics.Debugger.IsAttached)
    System.Diagnostics.Debugger.Launch(); 
&amp;nbsp;
&lt;span class="preproc"&gt;#endif&lt;/span&gt; 
...
&lt;/pre&gt;
 
This method will launch the debugger selection dialog, so I can choose the Visual Studio instance on which I have the project opened.&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4231643041612741920?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4231643041612741920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4231643041612741920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4231643041612741920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4231643041612741920'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/attach-vs-debugger-at-runtime.html' title='Attach the Visual Studio Debugger at runtime'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-5377179612063517707</id><published>2008-01-05T16:21:00.000-08:00</published><updated>2008-01-05T17:12:19.803-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Creating an object instance from an external assembly</title><content type='html'>For the following examples, I've created a class library for declaring the interface that I had implemented into an application named WindowsFormsApplication1.

Interface declaration:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; myInterface
{
    &lt;span class="kwrd"&gt;void&lt;/span&gt; callMe(&lt;span class="kwrd"&gt;string&lt;/span&gt; message);
}
&lt;/pre&gt;

The Remote Object was declared as:

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RemoteObject : System.MarshalByRefObject, myInterface
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; RemoteObject()
    {
        Console.WriteLine(&lt;span class="str"&gt;"Hello, World! (RemoteObject Constructor)"&lt;/span&gt;);
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#region&lt;/span&gt; myInterface Members
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; callMe(&lt;span class="kwrd"&gt;string&lt;/span&gt; message)
    {
        Console.WriteLine(&lt;span class="str"&gt;"callMe was called !!!"&lt;/span&gt;);
        Console.WriteLine(message);
    }
&amp;nbsp;
    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;
}
&lt;/pre&gt;

&lt;strong&gt;Method 1&lt;/strong&gt;: using reflection to load and execute code into the same application domain.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Loading the assembly&lt;/span&gt;
Assembly asm = Assembly.LoadFrom(&lt;span class="str"&gt;@"C:\TempDev\WindowsFormsApplication1.exe"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creating the instance we want to access&lt;/span&gt;
myInterface obj = asm.CreateInstance(&lt;span class="str"&gt;"WindowsFormsApplication1.RemoteObject"&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; myInterface;
&amp;nbsp;
&lt;span class="rem"&gt;// Executing some methods using the Interface&lt;/span&gt;
obj.callMe(&lt;span class="str"&gt;"testing message!"&lt;/span&gt;);
&lt;/pre&gt;

&lt;strong&gt;Method 2&lt;/strong&gt;: using application domains to load an execute code into a different domain:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Creating the domain&lt;/span&gt;
AppDomain domain = AppDomain.CreateDomain(&lt;span class="str"&gt;"myDomain"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Creating the instance we want to access&lt;/span&gt;
myInterface obj = domain.CreateInstanceFromAndUnwrap(&lt;span class="str"&gt;@"C:\TempDev\WindowsFormsApplication1.exe"&lt;/span&gt;, &lt;span class="str"&gt;"WindowsFormsApplication1.RemoteObject"&lt;/span&gt;) &lt;span class="kwrd"&gt;as&lt;/span&gt; myInterface;
&amp;nbsp;
&lt;span class="rem"&gt;// Executing some methods using the Interface&lt;/span&gt;
obj.callMe(&lt;span class="str"&gt;"testing message!"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Unloading the domain&lt;/span&gt;
AppDomain.Unload(domain);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-5377179612063517707?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/5377179612063517707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=5377179612063517707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5377179612063517707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/5377179612063517707'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/creating-object-instances-from-external.html' title='Creating an object instance from an external assembly'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-3974904257653760021</id><published>2008-01-05T14:24:00.000-08:00</published><updated>2008-01-05T16:42:43.091-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Application Domains</title><content type='html'>&lt;em&gt;"Application domains provide a flexible and secure method of isolating running applications."&lt;/em&gt; -- MSDN

They provide reliability, efficiency and security.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Creating the domain&lt;/span&gt;
AppDomain domain = AppDomain.CreateDomain(&lt;span class="str"&gt;"myDomain"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Access some domain's properties&lt;/span&gt;
Console.Write(&lt;span class="str"&gt;"{0} {1}"&lt;/span&gt;, domain.BaseDirectory, domain.FriendlyName);
&amp;nbsp;
&lt;span class="rem"&gt;// Executing another assembly into the new application domain&lt;/span&gt;
domain.ExecuteAssembly(&lt;span class="str"&gt;@"C:\TempDev\WindowsFormsApplication1.exe"&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Unloading the domain&lt;/span&gt;
AppDomain.Unload(domain);
&lt;/pre&gt;

Ensuring security with application domains:

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// We can use the Internet Zone, My Computer Zone, Untrusted Zone, etc.&lt;/span&gt;
&lt;span class="kwrd"&gt;object&lt;/span&gt;[] hostEvidence = { &lt;span class="kwrd"&gt;new&lt;/span&gt; Zone(System.Security.SecurityZone.Internet) };
Evidence myEvidence = &lt;span class="kwrd"&gt;new&lt;/span&gt; Evidence(hostEvidence, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Executing the assembly with our evidence&lt;/span&gt;
domain.ExecuteAssembly(&lt;span class="str"&gt;@"C:\TempDev\WindowsFormsApplication1.exe"&lt;/span&gt;, myEvidence);
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-3974904257653760021?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/3974904257653760021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=3974904257653760021' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3974904257653760021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/3974904257653760021'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2008/01/application-domains.html' title='Application Domains'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4454198588468653354</id><published>2007-12-30T20:05:00.000-08:00</published><updated>2008-02-09T09:52:23.853-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>IAsyncResult interface</title><content type='html'>There are a lot of asynchronous operations (APM: Asynchronous Programming Model) that we can perform using the .NET Framework.  Normally, they start by &lt;em&gt;BeginXXX&lt;/em&gt; and &lt;em&gt;EndXXX&lt;/em&gt;.  Here a little sample using an asynchronous operation to read a file stream. &lt;br&gt;&lt;br&gt;

In this code, we launch the &lt;em&gt;"asynchronous"&lt;/em&gt; operation and wait until it finished polling the &lt;em&gt;.IsCompleted&lt;/em&gt; property of &lt;em&gt;IAsyncResult&lt;/em&gt;.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] b = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[1000];
&amp;nbsp;
&lt;span class="rem"&gt;// Open the stream&lt;/span&gt;
FileStream fs = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileStream(&lt;span class="str"&gt;"C:\\ike.zip"&lt;/span&gt;, FileMode.Open, FileAccess.Read);
&amp;nbsp;
&lt;span class="rem"&gt;// Start the asynchronous operation&lt;/span&gt;
IAsyncResult ar = fs.BeginRead(b, 0, b.Length, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;);
&amp;nbsp;
&lt;span class="rem"&gt;// Wait until task is completed&lt;/span&gt;
&lt;span class="kwrd"&gt;while&lt;/span&gt; (!ar.IsCompleted)
{
    Thread.Sleep(1000);
    MessageBox.Show(&lt;span class="str"&gt;"not yet"&lt;/span&gt;);
}
&amp;nbsp;
MessageBox.Show(&lt;span class="str"&gt;"Completed"&lt;/span&gt; + fs.EndRead(ar).ToString());
&amp;nbsp;
fs.Close();
&lt;/pre&gt;

But, we really want to perform some asynchronous operation, so, we need to declare the asynchronous callback method like this:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MyAsyncCallback(IAsyncResult ar)
{
    FileStream fs = ar.AsyncState &lt;span class="kwrd"&gt;as&lt;/span&gt; FileStream;
&amp;nbsp;
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        MessageBox.Show(&lt;span class="str"&gt;"Completed"&lt;/span&gt; + fs.EndRead(ar).ToString());
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
    {
        MessageBox.Show(&lt;span class="str"&gt;"Error: "&lt;/span&gt;  + ex.Message);
    }
    &lt;span class="kwrd"&gt;finally&lt;/span&gt;
    {
        fs.Close();
    }
}
&lt;/pre&gt;

And call the &lt;em&gt;BeginRead&lt;/em&gt; as:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] b = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[1000];
&amp;nbsp;
FileStream fs = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileStream(&lt;span class="str"&gt;"C:\\ike.zip"&lt;/span&gt;, FileMode.Open, FileAccess.Read);
&amp;nbsp;
IAsyncResult ar = fs.BeginRead(b, 0, b.Length, &lt;span class="kwrd"&gt;new&lt;/span&gt; AsyncCallback(MyAsyncCallback), fs);
&lt;/pre&gt;

&lt;strong&gt;Points of interest:&lt;/strong&gt; &lt;br&gt;&lt;br&gt;
- We use the &lt;em&gt;AsyncState&lt;/em&gt; parameter to pass some important object to the callback method. &lt;br&gt;&lt;br&gt;
- Also, if some exception is thrown in the asynchronous operation, we'll be notified only when we call the EndRead method, so, we catch the exception in the callback.&lt;br&gt;&lt;br&gt;

&lt;strong&gt;Synchronizing UI Elements:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;

If we try to access UI elements in another thread than they were created, an exception will be raised, to avoid that, we can ask for the property &lt;em&gt;InvokeRequired&lt;/em&gt; in some UI elements such as forms, text boxes, list views, etc. When this property is true, we need to call the appropriated &lt;em&gt;Invoke&lt;/em&gt; method as follows:&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Delegate declaration&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;delegate&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ShowResult(&lt;span class="kwrd"&gt;string&lt;/span&gt; message);
&amp;nbsp;
&lt;span class="rem"&gt;// Callback method&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MyAsyncCallback(IAsyncResult ar)
{
    FileStream fs = ar.AsyncState &lt;span class="kwrd"&gt;as&lt;/span&gt; FileStream;
&amp;nbsp;
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        ShowResultInt(&lt;span class="str"&gt;"Completed"&lt;/span&gt; + fs.EndRead(ar).ToString());
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)
    {
        MessageBox.Show(&lt;span class="str"&gt;"Error: "&lt;/span&gt; + ex.Message);
    }
    &lt;span class="kwrd"&gt;finally&lt;/span&gt;
    {
        fs.Close();
    }
}
&amp;nbsp;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ShowResultInt(&lt;span class="kwrd"&gt;string&lt;/span&gt; message)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (txtResult.InvokeRequired)
        &lt;span class="rem"&gt;// Invoke is required, we are in another thread than UI elements&lt;/span&gt;
        txtResult.Invoke(&lt;span class="kwrd"&gt;new&lt;/span&gt; ShowResult(ShowResultInt), message);
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
        &lt;span class="rem"&gt;// Not invoke required, then we can access UI elements directly&lt;/span&gt;
        txtResult.Text = message;
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-4454198588468653354?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/4454198588468653354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=4454198588468653354' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4454198588468653354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/4454198588468653354'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2007/12/iasyncresult-interface.html' title='IAsyncResult interface'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-7560708590426459382</id><published>2007-12-30T15:16:00.000-08:00</published><updated>2008-02-09T09:53:17.924-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Using the ThreadPool.RegisterWaitForSingleObject</title><content type='html'>For creating threads in the ThreadPool, we use the &lt;em&gt;QueueUserWorkItem&lt;/em&gt;:

&lt;pre class="csharpcode"&gt;
ThreadPool.QueueUserWorkItem(&lt;span class="kwrd"&gt;new&lt;/span&gt; WaitCallback(FunctionCall), PersonalizeDataForTherad);
&lt;/pre&gt;

Or, for creating a timed thread in the ThreadPool, we use &lt;em&gt;RegisterWaitForSingleObject&lt;/em&gt;:

&lt;pre class="csharpcode"&gt;
ThreadPool.RegisterWaitForSingleObject(AutoResetEventObject, &lt;span class="kwrd"&gt;new&lt;/span&gt; WaitOrTimerCallback(FunctionCall), PersonalizeData, TimeOut, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
&lt;/pre&gt;

This method is useful for performing timed or event signed tasks.  The &lt;em&gt;RegisteredWaitHandle&lt;/em&gt; can be used to unregister the callback.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Declaring our handle.  It could be declared alone or as part of &lt;/span&gt;
&lt;span class="rem"&gt;// the state class we can pass to the RegisterWaitForSingleObject method.&lt;/span&gt;
RegisteredWaitHandle rwh;
AutoResetEvent arevent = &lt;span class="kwrd"&gt;new&lt;/span&gt; AutoResetEvent(&lt;span class="kwrd"&gt;false&lt;/span&gt;);
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Our callback procedure&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; wit(&lt;span class="kwrd"&gt;object&lt;/span&gt; state, &lt;span class="kwrd"&gt;bool&lt;/span&gt; btimeOut)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (btimeOut)
    {
        &lt;span class="rem"&gt;// Perform some timed task&lt;/span&gt;
        MessageBox.Show(&lt;span class="str"&gt;"1: "&lt;/span&gt; + DateTime.Now.ToShortTimeString());
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
    {
        &lt;span class="rem"&gt;// Perform some signed task or unregister the WaitHandle&lt;/span&gt;
        rwh.Unregister(&lt;span class="kwrd"&gt;null&lt;/span&gt;);
    }
}
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Now, we can create the WaitHandle&lt;/span&gt;
&lt;span class="rem"&gt;// We can use the state object to pass more information to the callback&lt;/span&gt;
rwh = ThreadPool.RegisterWaitForSingleObject(arevent, &lt;span class="kwrd"&gt;new&lt;/span&gt; WaitOrTimerCallback(wit), &lt;span class="kwrd"&gt;null&lt;/span&gt;, 2000, &lt;span class="kwrd"&gt;false&lt;/span&gt;);
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// After we were used the callback, we can sign the finished event&lt;/span&gt;
arevent.Set();&lt;/pre&gt;

An util use of this pattern, can be achieved by cancelling asynchronous delegates when time out.

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Declaring our handle.&lt;/span&gt;
RegisteredWaitHandle rwh;
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Creating some asynchronous operation&lt;/span&gt;
IAsyncResult result = someobject.BeginGetResponse(&lt;span class="kwrd"&gt;new&lt;/span&gt; AsyncCallback(someAsyncMethod), state);
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Creating the waiting callback&lt;/span&gt;
rwh = ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, &lt;span class="kwrd"&gt;new&lt;/span&gt; WaitOrTimerCallback(ScanTimeoutCallback), result, 30000, &lt;span class="kwrd"&gt;true&lt;/span&gt;);
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Timeout callback&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ScanTimeoutCallback (&lt;span class="kwrd"&gt;object&lt;/span&gt; state, &lt;span class="kwrd"&gt;bool&lt;/span&gt; timedOut) 
{ 
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (timedOut) 
    {
        &lt;span class="rem"&gt;// Cancel the asynchronous operation by timeout&lt;/span&gt;
        RequestState reqState = (RequestState)result.AsyncState;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (reqState != &lt;span class="kwrd"&gt;null&lt;/span&gt;) 
            reqState.request.Abort();
    }
    &lt;span class="kwrd"&gt;else&lt;/span&gt;
    {
        &lt;span class="rem"&gt;// Unregister the WaitHandle&lt;/span&gt;
        rwh.Unregister(&lt;span class="kwrd"&gt;null&lt;/span&gt;);
    }
}
&lt;/pre&gt;

References:&lt;br&gt;&lt;br&gt;

&lt;a href="http://www.c-sharpcorner.com/UploadFile/Ashish1/ThreadPool11052005132510PM/ThreadPool.aspx"&gt;How do I use ThreadPool in C# and .NET?&lt;/a&gt; by Ashish Singhal
&lt;a href="http://www.developerfusion.co.uk/show/4654"&gt;Asynchronous HttpWebRequest&lt;/a&gt; by stevencohn&lt;br&gt;
&lt;a href="http://www.c-sharpcorner.com/UploadFile/Ashish1/RegisterWaitForSingleObject11042005191647PM/RegisterWaitForSingleObject.aspx"&gt;RegisterWaitForSingleObject in ThreadPool&lt;/a&gt; By Ashish Singhal&lt;br&gt;
&lt;a href="http://www.c-sharpcorner.com/UploadFile/mmehta/Multithreading411162005051609AM/Multithreading4.aspx"&gt;Multithreading Part 4: The ThreadPool, Timer Classes and Asynchronous Programming&lt;/a&gt; By Manisha Mehta&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-7560708590426459382?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/7560708590426459382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=7560708590426459382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7560708590426459382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/7560708590426459382'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2007/12/using-threadpoolregisterwaitforsingleob.html' title='Using the ThreadPool.RegisterWaitForSingleObject'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-6681220933749639313</id><published>2007-12-30T13:12:00.000-08:00</published><updated>2007-12-30T13:23:18.795-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>EventHandler delegate</title><content type='html'>MSDN Says: &lt;em&gt;"The advantage of using &lt;strong&gt;EventHandler&lt;(Of &lt;(TEventArgs&gt;)&gt;)&lt;/strong&gt; is that you do not need to code your own custom delegate if your event generates event data. Additionally, the .NET Framework needs only one implementation to support &lt;strong&gt;EventHandler&lt;(Of &lt;(TEventArgs&gt;)&gt;)&lt;/strong&gt; regardless of the event data type you substitute for the generic type parameter."&lt;/em&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Here, MyEventArgs class declaration&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyEventArgs : EventArgs
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; msg;
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; MyEventArgs(&lt;span class="kwrd"&gt;string&lt;/span&gt; messageData)
    {
        msg = messageData;
    }
&amp;nbsp;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Message
    { 
        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; msg; } 
        set { msg = &lt;span class="kwrd"&gt;value&lt;/span&gt;; }
    }
}
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Declaring the event property&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; EventHandler&amp;lt;MyEventArgs&amp;gt; SampleEvent;
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Invoking the event&lt;/span&gt;
&lt;span class="kwrd"&gt;if&lt;/span&gt; (SampleEvent != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    SampleEvent(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; MyEventArgs(val));
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Subscribing to the event &lt;/span&gt;
MyClass.SampleEvent += &lt;span class="kwrd"&gt;new&lt;/span&gt; EventHandler&amp;lt;MyEventArgs&amp;gt;(SampleEventHandler);
&amp;nbsp;
...
&amp;nbsp;
&lt;span class="rem"&gt;// Where SampleEventHandler was implemented as&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SampleEventHandler(&lt;span class="kwrd"&gt;object&lt;/span&gt; src, MyEventArgs mea)
{
    Console.WriteLine(mea.Message);
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5772302-6681220933749639313?l=olondono.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://olondono.blogspot.com/feeds/6681220933749639313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5772302&amp;postID=6681220933749639313' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6681220933749639313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5772302/posts/default/6681220933749639313'/><link rel='alternate' type='text/html' href='http://olondono.blogspot.com/2007/12/eventhandler-delegate.html' title='EventHandler delegate'/><author><name>Oscar Londono</name><uri>http://www.blogger.com/profile/10159430789458196643</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://3.bp.blogspot.com/_klu-RAVtjKg/SVo0DY3BRRI/AAAAAAAAAC4/csziPL6sSwk/S220/OL3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5772302.post-4893256882096085687</id><published>2007-12-24T09:22:00.000-08:00</published><updated>2008-02-09T09:54:02.724-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MCTS'/><category scheme='http://www.blogger.com/atom/ns#' term='70-536'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Thread synchronization</title><content type='html'>For thread synchronization, we can use the &lt;em&gt;lock&lt;/em&gt; statement that permits access a shared object by one thread at once.  Also, we can use the &lt;em&gt;AutoResetEvent&lt;/em&gt; and the &lt;em&gt;ManualResetEvent&lt;/em&gt; to send some signal to our threads.&lt;br&gt;&lt;br&gt;

&lt;pre class="csharpcode"&gt;
&lt;span class="rem"&gt;// Declaring our event for signal threads we are closing the form&lt;/span&gt;
&lt;span class="kwrd"&gt;private&lt;/span&gt; AutoResetEvent MyCloseEvent = &lt;span class="kwrd"&gt;new&lt;/span&gt; AutoResetEvent(&lt;span class="kwrd"&gt;false&lt;/span&gt;);
&amp;nbsp;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; MyThreadProc()
{
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        &lt;span class="rem"&gt;// Enqueue some values&lt;/span&gt;
        &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; ; i++)
        {
            &lt;span class="rem"&gt;// Signal for finish this thread&lt;/span&gt;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (MyCloseEvent.WaitOne(0, &lt;span class="kwrd"&gt;false&lt;/span&gt;))
                &lt;span class="kwrd"&gt;break&lt;/span&gt;;
&amp;nbsp;
            &lt;span class="rem"&gt;// Thread synchronization&lt;/span&gt;
            &lt;span class="kwrd"&gt;lock&lt;/span&gt; (MyQueue.SyncRoot)
                MyQueue.Enqueue(i);
&amp;nbsp;
            Thread.Sleep(500);
        }
&amp;nbsp;
        Console.WriteLine(&lt;span class="str"&gt;"Finished"&lt;/span&gt;);
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (ThreadAbortException)
    {
        &lt;span class="rem"&gt;// Perform the cleanup process&lt;/span&gt;
        Console.WriteLine(&lt;span class="str"&gt;"Aborted"&lt;/span&gt;);
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt;
    {
        Console.WriteLine(&lt;span class="str"&gt;"Error"&lt;/span&gt;);
    }
}
&amp;nbsp;
&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"
