<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title>Jelle Druyts</title>
  <link rel="alternate" type="text/html" href="http://jelle.druyts.net/" />
  <link rel="self" href="http://jelle.druyts.net/SyndicationService.asmx/GetAtom" />
  <icon>favicon.ico</icon>
  <updated>2008-06-02T04:18:29.8767301-07:00</updated>
  <author>
    <name>Jelle Druyts</name>
  </author>
  <subtitle>Reflection.Emit()</subtitle>
  <id>http://jelle.druyts.net/</id>
  <generator uri="http://www.dasblog.net" version="2.0.7180.0">DasBlog</generator>
  <entry>
    <title>Extracting OLE embedded images from emails in Outlook</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2008/06/02/ExtractingOLEEmbeddedImagesFromEmailsInOutlook.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=d9469f09-7c32-40dc-95a9-4a1686f787ca</id>
    <published>2008-06-02T04:18:29.8767301-07:00</published>
    <updated>2008-06-02T04:18:29.8767301-07:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/General" label="Blog/General" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cGeneral" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Blog/Programming/Samples" label="Blog/Programming/Samples" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7cSamples" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
While it seemed a simple requirement, saving all attachments from emails in Outlook
to disk proved to be <em>challenging</em> - to say the least. Using the <a href="http://msdn.microsoft.com/en-us/library/aa221870.aspx">Outlook
Object Model</a>, it's quite easy to enumerate all emails in a folder, look at their
attachments and call the <code><a href="http://msdn.microsoft.com/en-us/library/aa210277(office.11).aspx">SaveAsFile</a></code> method
on them. However, for OLE-type attachments (typically images), this throws a <code>COMException</code> saying:
"Outlook cannot do this action on this type of attachment". While looking for alternatives
or workarounds, I found nothing but confirmation that this is indeed not an easy task
- even from <a href="http://www.dimastr.com/">Dmitry Streblechenko</a>, Outlook MVP
and creator of the excellent and very affordable <a href="http://www.dimastr.com/redemption/">Outlook
Redemption library</a>: "<a href="http://www.pcreview.co.uk/forums/thread-1841126.php">If
you mean embedded graphics objects in the RTF messages, there is not much you can
do [...] You can look at the storage itself to figure that out, but I've never tried
that</a>".
</p>
        <p>
Ultimately, after lots of trial and error, I did manage to find a fairly easy way
to save these OLE embedded images by (mis)using the clipboard. Basically, I retrieve
the attachment’s <code><a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.ole.interop.istorage.aspx">IStorage</a></code> OLE
interface (available through <a href="http://www.dimastr.com/redemption">Redemption</a>)
and call <code><a href="http://msdn.microsoft.com/en-us/library/ms694338(VS.85).aspx">OleLoad</a></code> on
it to have OLE load the contents and retrieve an <code><a href="http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.ole.interop.idataobject.aspx">IDataObject</a></code>.
The magic trick is to place that <code>IDataObject</code> on the clipboard and retrieve
the actual image from the clipboard (so that the clipboard itself handles the nasty
OLE details).
</p>
        <p>
          <a href="http://en.wikipedia.org/wiki/Borat">Great success</a>! At least for a moment.
That already worked for Device Independent Bitmaps, but Outlook also uses Enhanced
Metafiles (wmf) and apparently there is <a href="http://support.microsoft.com/kb/323530">a
problem with the .NET Framework when it comes to handling Enhanced Metafiles from
the clipboard</a>. So I needed some additional COM interop to handle these Enhanced
Metafiles as well, which made the code slightly more difficult to read but fortunately
still effective. The trick here is to make sure you have a valid handle to pass to <code><a href="http://msdn.microsoft.com/en-us/library/aa932577.aspx">OpenClipboard</a></code>.
Because I didn't have access to a form or other type of existing control, I just created
a dummy button and used its handle.
</p>
        <p>
Finally, be aware that to access OLE functionality, you need a Single Threaded Apartment
(STA) model. Of course I was in an MTA context, so from there I launched a new thread
which I put to STA - after that, everything was golden.
</p>
        <p>
Below is the full code using <a href="http://www.dimastr.com/redemption/rdo/default.htm">Redemption
Data Objects (RDO)</a>, hopefully this will save other people a few hours in trying
to achieve the same thing...
</p>
        <pre>public static class Program
{
  public static void Main()
  {
    // Calling code should always ensure to be in STA.
    Thread staThread = new Thread(new ThreadStart(SaveOutlookAttachments));
    staThread.SetApartmentState(ApartmentState.STA);
    staThread.Start();
  }

  private static void SaveOutlookAttachments()
  {
    RDOSession session = new RDOSessionClass();
    RDOFolder inbox = session.GetDefaultFolder(rdoDefaultFolders.olFolderInbox);
    string attachmentRootPath = AppDomain.CurrentDomain.BaseDirectory;
    foreach (RDOMail mail in inbox.Items)
    {
      foreach (RDOAttachment attachment in mail.Attachments)
      {
        if (attachment.Type == rdoAttachmentType.olOLE)
        {
          // We don't have a filename for this type of attachment, create a unique one.
          string filename = Guid.NewGuid().ToString() + ".png";
          string attachmentPath = Path.Combine(attachmentRootPath, filename);
          // We assume here that only images will be stored as OLE attachments.
          // We save them as PNG to keep the file size small.
          SaveOleImageAttachment(attachment, attachmentPath, ImageFormat.Png);
        }
        else
        {
          string attachmentPath = Path.Combine(attachmentRootPath, attachment.FileName);
          attachment.SaveAsFile(attachmentPath);
        }
      }
    }
  }

  private static void SaveOleImageAttachment(RDOAttachment attachment, string filePath, ImageFormat format)
  {
    // Use the OLE storage interface to load the OLE document into a DataObject.
    IStorage oleStorage = (IStorage)attachment.OleStorage;
    object oleDataObject;
    OleLoad(oleStorage, ref IDataObjectGuid, null, out oleDataObject);

    // Copy the OLE DataObject to the clipboard so it can handle the internals.
    Clipboard.SetDataObject(oleDataObject, false);

    // Try to retrieve an image back from the clipboard.
    if (Clipboard.ContainsData(DataFormats.EnhancedMetafile))
    {
      // Enhanced Metafiles cannot be handled natively from .NET.
      // Use the Clipboard directly to retrieve the data.

      // We need a valid handle, otherwise this won't work.
      Button dummy = new Button();
      if (OpenClipboard(dummy.Handle))
      {
        try
        {
          if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
          {
            IntPtr metafileData = GetClipboardData(CF_ENHMETAFILE);
            if (metafileData != IntPtr.Zero)
            {
              using (Metafile metafile = new Metafile(metafileData, true))
              {
                metafile.Save(filePath, format);
              }
            }
          }
        }
        finally
        {
          EmptyClipboard();
          CloseClipboard();
        }
      }
    }
    else if (Clipboard.ContainsImage())
    {
      using (Image image = Clipboard.GetImage())
      {
        if (image != null)
        {
          image.Save(filePath, format);
        }
      }
    }
  }

  [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  private static extern bool OpenClipboard(IntPtr hWndNewOwner);
  [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  private static extern bool CloseClipboard();
  [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  private static extern IntPtr GetClipboardData(uint format);
  [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  private static extern bool IsClipboardFormatAvailable(uint format);
  [DllImport("user32.dll")]
  private static extern bool EmptyClipboard();
  [DllImport("ole32.dll")]
  private static extern int OleLoad(IStorage pStg, [In] ref Guid riid, IOleClientSite pClientSite, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObj);

  private static Guid IDataObjectGuid = new Guid("0000010E00000000C000000000000046");
  private const uint CF_ENHMETAFILE = 14;
}</pre>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=d9469f09-7c32-40dc-95a9-4a1686f787ca" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Just Released: Mollom for .NET v1.0!</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2008/05/18/JustReleasedMollomForNETV10.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=52ccc103-e22d-4d75-8b1b-4ef2360a836a</id>
    <published>2008-05-18T09:22:48.80025-07:00</published>
    <updated>2008-05-18T09:22:48.80025-07:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/General" label="Blog/General" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cGeneral" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
My friend <a href="http://www.buytaert.net/">Dries Buytaert</a> - known all around
the world for creating <a href="http://drupal.org/">Drupal</a> (the wildly popular
open source content management system) and <a href="http://www.buytaert.net/tag/axl">Axl</a> (the
incredibly cute kid he co-created with my even better friend <a href="http://www.buytaert.net/tag/karlijn">Karlijn</a>)
- asked me a few months ago if I had any trouble with spam on my blog... It turned
out he was building <a href="http://mollom.com/">Mollom</a>, a solution for fighting
spam and automating content monitoring, and was looking for beta testers. I immediately
jumped aboard and implemented a .NET client API for his service and integrated it
into <a href="http://codeplex.com/dasBlog/">dasBlog</a>, the blog engine I'm using.
</p>
        <p>
Now that <a href="http://mollom.com/">Mollom</a> and its <a href="http://mollom.com/api">API
and developer documentation</a> have finally been released (in public beta), I've
packaged my client library as well and published it on <a href="http://www.codeplex.com/">CodePlex</a>:
see the <a href="http://www.codeplex.com/mollom">Mollom for .NET homepage</a>.
</p>
        <p>
          <em>Mollom's purpose is to dramatically reduce the effort of keeping your websites
clean and the quality of their user-generated content high. Currently, Mollom is a
spam-killing, one-two punch combination of a state-of-the-art spam filter and CAPTCHA
server. </em>
        </p>
        <p>
I have to say it's working really well for me, I don't get any spam at all anymore
through my blog, and the XML-RPC API that Mollom provides is easy and straight-forward
to use. And, of course, if you develop on .NET then it's even easier to talk to Mollom
using my client API. As a very basic sample, this should give you an idea of how easy
it is to have Mollom classify a piece of content:
</p>
        <pre>MollomClient client = new MollomClient(privateKey, publicKey);
ContentCheck result = client.CheckContent(postTitle, postBody, authorName, authorMail, authorUrl, authorIPAddress);
if (result.Classification == ContentClassification.Spam)
{     // Handle spam here...
}</pre>
        <p>
All information, downloads and documentation is available on the <a href="http://www.codeplex.com/mollom">Mollom
for .NET homepage on CodePlex</a>, so rush out and let me know what you think!
</p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=52ccc103-e22d-4d75-8b1b-4ef2360a836a" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Updated: Setting up Source Server for TFS Builds</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2008/04/30/UpdatedSettingUpSourceServerForTFSBuilds.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=6724aea2-53bc-46d2-ac1d-bb5b241bd7e3</id>
    <published>2008-04-30T03:20:47.160125-07:00</published>
    <updated>2008-04-30T03:20:47.160125-07:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Blog/Programming/.NET/VS.NET" label="Blog/Programming/.NET/VS.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET%7cVS.NET" />
    <category term="Blog/Programming/TeamSystem" label="Blog/Programming/TeamSystem" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7cTeamSystem" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
Just a quick note to let you know that I've updated my guide on <a href="http://jelle.druyts.net/2007/12/09/SettingUpSourceServerForTFSBuilds.aspx">Setting
up Source Server for TFS Builds</a>, since I just found out that there is an issue
with Build Definitions that contain spaces. The fix is fairly easy though:
</p>
        <ul>
          <li>
In TFIndex.cmd (on the build server), remove the quotes around the <code>%1</code> argument
for SYMBOLS: 
</li>
        </ul>
        <pre>
          <strike>@call "%~dp0SSIndex.cmd" -SYSTEM=TF -SYMBOLS="%1" %*</strike> @call "%~dp0SSIndex.cmd"
-SYSTEM=TF -SYMBOLS=%1 %*</pre>
        <ul>
          <li>
In the Team Build Script (in Source Control), add XML-escaped quotes around the <code>$(BinariesRoot)</code> argument: 
</li>
        </ul>
        <pre>
          <strike>&lt;Exec Command="&amp;quot;C:\Program Files\Debugging Tools for Windows\sdk\srcsrv\TFIndex.cmd&amp;quot;
$(BinariesRoot)"<br />
      WorkingDirectory="$(SolutionRoot)" /&gt;</strike> &lt;Exec
Command="&amp;quot;C:\Program Files\Debugging Tools for Windows\sdk\srcsrv\TFIndex.cmd&amp;quot;
&amp;quot;$(BinariesRoot)&amp;quot;"<br />
      WorkingDirectory="$(SolutionRoot)" /&gt;</pre>
        <p>
For the full setup instructions, please refer to the original post on <a href="http://jelle.druyts.net/2007/12/09/SettingUpSourceServerForTFSBuilds.aspx">Setting
up Source Server for TFS Builds</a>.
</p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=6724aea2-53bc-46d2-ac1d-bb5b241bd7e3" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Mortgage Loan Excel Sheet</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2008/03/07/MortgageLoanExcelSheet.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=8653bbfd-3937-4a3f-a1f5-9f4580242d9b</id>
    <published>2008-03-07T04:03:40.678-08:00</published>
    <updated>2008-03-07T04:20:12.4445-08:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/General" label="Blog/General" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cGeneral" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
If anybody would be interested, I've recently put together an Excel sheet that calculates
the payment table ("aflossingstabel") for a loan, i.e. for each month it shows you
how much you need to pay, what the interest is, what the remaining capital is, ...
</p>
        <p>
I've only modeled two options (that were relevant to me): fixed monthly payments ("vaste
mensualiteit") - where you pay the same consant amount every month - and fixed capital
("vaste kapitaalaflossing") payments - where you pay off a fixed amount of capital
but a variable amount of interest (making it a decreasing loan).
</p>
        <p>
When I showed this to my bank, they were actually pretty impressed so I figured somebody
else might benefit from this :-) And yes, this means we just bought a house, yay!
But the examples in the Excel sheet and below are not ours, if you were wondering
;-) 
</p>
        <p>
Features:
</p>
        <ul>
          <li>
Calculates payment tables for loans up to 40 years 
</li>
          <li>
Shows payment graphs up to 25 years (by default, you can enlarge this of course) 
</li>
          <li>
Calculates how much of your total payments are actually interest payments (try not
to weep when looking at this) 
</li>
          <li>
Allows you to compare different loan options (amount, duration, interest rate), e.g.
to compare different bank proposals</li>
        </ul>
        <p>
Download here: <a href="http://jelle.druyts.net/content/binary/Loans.zip">Loans.zip
(108 KB)</a>.
</p>
        <p>
Note that you can only open this in Excel 2007 since it uses some financial functions
only available there. And although the calculations were very accurate (just a few
cents deviation on the total amounts compared to the bank's proposals), it goes without
saying that you use this at your own financial risk :-)
</p>
        <p>
Example payment table:
</p>
        <p>
          <a href="http://jelle.druyts.net/content/binary/WindowsLiveWriter/MortgageLoanExcelSheet_B780/LoanFixedPaymentSheet_2.png">
            <img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height="619" alt="LoanFixedPaymentSheet" src="http://jelle.druyts.net/content/binary/WindowsLiveWriter/MortgageLoanExcelSheet_B780/LoanFixedPaymentSheet_thumb.png" width="551" border="0" />
          </a>
        </p>
        <p>
Example yearly graph for a fixed payment (constant) loan:
</p>
        <p>
          <a href="http://jelle.druyts.net/content/binary/WindowsLiveWriter/MortgageLoanExcelSheet_B780/LoanFixedPayment_4.png">
            <img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height="384" alt="LoanFixedPayment" src="http://jelle.druyts.net/content/binary/WindowsLiveWriter/MortgageLoanExcelSheet_B780/LoanFixedPayment_thumb_1.png" width="597" border="0" />
          </a>
        </p>
        <p>
Example monthly graph for a fixed capital (decreasing) loan:
</p>
        <p>
          <a href="http://jelle.druyts.net/content/binary/WindowsLiveWriter/MortgageLoanExcelSheet_B780/LoanFixedCapital_2.png">
            <img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height="472" alt="LoanFixedCapital" src="http://jelle.druyts.net/content/binary/WindowsLiveWriter/MortgageLoanExcelSheet_B780/LoanFixedCapital_thumb.png" width="686" border="0" />
          </a>
        </p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=8653bbfd-3937-4a3f-a1f5-9f4580242d9b" />
      </div>
    </content>
  </entry>
  <entry>
    <title>My &amp;quot;Deep Dive Into The Guidance Automation Toolkit&amp;quot; presentation now online!</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2008/03/03/MyQuotDeepDiveIntoTheGuidanceAutomationToolkitquotPresentationNowOnline.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=4ae2894a-8c87-4ee2-8da2-0e94dd199b11</id>
    <published>2008-03-03T01:39:16.0013706-08:00</published>
    <updated>2008-03-03T01:39:16.0013706-08:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/General" label="Blog/General" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cGeneral" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Blog/Programming/.NET/DSLs" label="Blog/Programming/.NET/DSLs" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET%7cDSLs" />
    <category term="Blog/Programming/.NET/GuidanceAutomation" label="Blog/Programming/.NET/GuidanceAutomation" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET%7cGuidanceAutomation" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
        </p>
        <p>
          <a href="http://blogs.msdn.com/tommer">Tom</a>'s team has been kind enough to put
my session of last year's <a href="http://www.techdays.be/">TechDays</a> (then still
known as the Developer &amp; IT Pro Days) online on <a href="http://www.microsoft.com/belux/msdn/nl/chopsticks/default.aspx">MSDN
Chopsticks</a>. You can find my "<a href="http://www.microsoft.com/belux/msdn/nl/chopsticks/default.aspx?id=10">Deep
Dive Into The Guidance Automation Toolkit</a>" presentation at <a title="http://www.microsoft.com/belux/msdn/nl/chopsticks/default.aspx?id=10" href="http://www.microsoft.com/belux/msdn/nl/chopsticks/default.aspx?id=10">http://www.microsoft.com/belux/msdn/nl/chopsticks/default.aspx?id=10</a>.
Everything I said back then is still relevant today, so if you missed it last year
you can now catch up for free :-)
</p>
        <p>
And in the light of Software Factory technologies, it also makes a nice preparation
for my talk on <a href="http://jelle.druyts.net/2008/02/18/DSLToolsSessionAtTechDaysInBelgium.aspx">Domain-Specific
Development with Visual Studio DSL Tools</a> next week. My session is <a href="http://www.microsoft.com/belux/heroeshappenhere/program.aspx">scheduled
on Thursday March 13 at 10:45</a>. I'm really looking forward to it, and I hope to
see you there!
</p>
        <p>
          <a title="TechDays 2008" href="http://www.techdays.be/">
            <img src="http://jelle.druyts.net/content/binary/WindowsLiveWriter/DSLToolssessionatTechDaysinBelgium_7C86/signature_speaker_3.gif" />
          </a>
        </p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=4ae2894a-8c87-4ee2-8da2-0e94dd199b11" />
      </div>
    </content>
  </entry>
  <entry>
    <title>DSL Tools session at TechDays in Belgium</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2008/02/18/DSLToolsSessionAtTechDaysInBelgium.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=a563821e-c875-4239-9be6-59156d8c3955</id>
    <published>2008-02-17T23:56:39.8729672-08:00</published>
    <updated>2008-02-17T23:56:39.8729672-08:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/General" label="Blog/General" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cGeneral" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Blog/Programming/.NET/DSLs" label="Blog/Programming/.NET/DSLs" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET%7cDSLs" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
The <a href="http://www.techdays.be">annual Belgian tech-fest for Microsoft developers,
architects and IT pro's</a> is coming to Ghent again soon, and I'm once again proud
to host a session in the Developers track for <a href="http://www.techdays.be">TechDays</a>!
</p>
        <blockquote>
          <p>
            <strong>Domain Specific Development with Visual Studio Domain Specific Language (DSL)
Tools</strong>
          </p>
          <p>
            <em>As one of the pillars of the Software Factories initiative, Domain Specific Languages
(DSLs) provide a way to describe your business domain in a language closer to the
actual problem than using traditional programming code. </em>
          </p>
          <p>
            <em>The Visual Studio Domain Specific Language Tools allow developers to create their
own graphical designers and code generation tools – much like the ones you can find
in Visual Studio today, such as the Class Designer. </em>
          </p>
          <p>
            <em>In this session, you will learn how to develop your own DSLs inside Visual Studio
and see an example of a real-world DSL that simplifies your life as a developer: the <a href="http://www.codeplex.com/csd">Configuration
Section Designer</a>.</em>
          </p>
          <p>
            <a title="TechDays 2008" href="http://www.techdays.be">
              <img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="120" alt="TechDays 2008" src="http://jelle.druyts.net/content/binary/WindowsLiveWriter/DSLToolssessionatTechDaysinBelgium_7C86/signature_speaker_3.gif" width="365" border="0" />
            </a>
          </p>
        </blockquote>
        <p>
          <strong>Heroes are Assembled { in Software Factories } :-)</strong>
        </p>
        <p>
Hope to see you there!
</p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=a563821e-c875-4239-9be6-59156d8c3955" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Just Released: BuildCop v1.0!</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2008/02/05/JustReleasedBuildCopV10.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=f9db393b-5ad8-482a-8d0b-1b8823662d67</id>
    <published>2008-02-05T13:37:20.5625-08:00</published>
    <updated>2008-02-05T13:37:20.5625-08:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/General" label="Blog/General" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cGeneral" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Projects/BuildCop" label="Projects/BuildCop" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Projects%7cBuildCop" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
It is with great pleasure that I'm finally ready to release another open source tool
on <a href="http://www.codeplex.com/">CodePlex</a>: <a href="http://www.codeplex.com/BuildCop">BuildCop</a>.
</p>
        <p>
          <em>BuildCop is a tool that analyzes MSBuild project files (interactively or during
e.g. a daily build) according to a customizable set of rules and generates reports
- e.g. is strong naming enabled, are certain project properties set correctly, is
XML documentation being generated, are assembly references correct, are naming conventions
respected, ...</em>
        </p>
        <p>
This has grown out of a quick-and-dirty tool to check various build settings in a
large customer project (to make sure that the developers were sticking to the guidelines),
and has evolved into quite a clean, flexible and customizable tool that you can now
start using as well.
</p>
        <p>
All information, downloads and documentation is available on the <a href="http://www.codeplex.com/BuildCop">BuildCop
homepage on CodePlex</a>, so rush out and let me know what you think!
</p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=f9db393b-5ad8-482a-8d0b-1b8823662d67" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Just Released: Configuration Section Designer</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2007/12/30/JustReleasedConfigurationSectionDesigner.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=64866735-a363-48d3-b491-76a7ced86390</id>
    <published>2007-12-30T08:21:30.40625-08:00</published>
    <updated>2007-12-30T08:21:30.40625-08:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Blog/Programming/.NET/DSLs" label="Blog/Programming/.NET/DSLs" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET%7cDSLs" />
    <category term="Projects/CSD" label="Projects/CSD" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Projects%7cCSD" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
I just released my first domain specific language to the public! The <a href="http://www.codeplex.com/csd">Configuration
Section Designer</a> is a Visual Studio add-in that allows you to graphically design
.NET Configuration Sections and automatically generates all the required code and
a schema definition (XSD) for them.
</p>
        <p>
          <a href="http://jelle.druyts.net/content/binary/WindowsLiveWriter/JustReleasedConfigurationSectionDesigner_F40F/ConfigurationSectionDesigner_2.jpg">
            <img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="435" alt="The Configuration Section Designer In Action" src="http://jelle.druyts.net/content/binary/WindowsLiveWriter/JustReleasedConfigurationSectionDesigner_F40F/ConfigurationSectionDesigner_thumb.jpg" width="640" border="0" />
          </a>
        </p>
        <p>
For all information, downloads, source code, work item tracking and discussions visit <a title="http://www.codeplex.com/csd" href="http://www.codeplex.com/csd">http://www.codeplex.com/csd</a>.
</p>
        <p>
The Configuration Section Designer is built on Visual Studio 2008 with the very excellent <a href="http://msdn.microsoft.com/vstudio/dsltools">DSL
Tools</a>. Instead of publishing it here on the blog as I normally do with my pet
projects, I've decided to host it as open source software on <a href="http://www.codeplex.com/">CodePlex</a> so
that hopefully other people will find it interesting enough to contribute and make
it even more powerful. This also gives me the chance to test-drive CodePlex in a real
project, and so far it's been working great so I'll probably be moving more projects
to it.
</p>
        <p>
Anyway, if you have Configuration Sections that you're currently writing by hand,
I encourage you to try this and let me know how it works for you. I'm pretty excited
about it, I've only published it yesterday evening and it's already got over 40 downloads
and a good feature suggestion of someone that's been porting his hand-written code
to the designer! Good times!
</p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=64866735-a363-48d3-b491-76a7ced86390" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Just Released: E = m c² v2.1!</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2007/12/28/JustReleasedEMCV21.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=21aa7d3c-4363-4684-8be7-b7ff0d49be48</id>
    <published>2007-12-28T05:15:25.953-08:00</published>
    <updated>2007-12-28T05:25:00.34375-08:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/General" label="Blog/General" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cGeneral" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Projects/Emc" label="Projects/Emc" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Projects%7cEmc" />
    <category term="Projects/Emc/Download" label="Projects/Emc/Download" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Projects%7cEmc%7cDownload" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
It's taken <em>way</em> too long to remind myself to release a new version of <a href="http://jelle.druyts.net/emc/">E
= m c²</a> - so finally, here goes: <a href="http://jelle.druyts.net/emc/Download.html">v2.1
is out the door</a>! It even comes with source code again! What a perfect Christmas
present for 3.4 gazillion E = m c² users*! Actually, there are quite a lot of extra
features so if I would've released a bit more sensibly over the last months then it
probably would've been v2.4 or so already. Anyway...
</p>
        <p>
          <img src="http://jelle.druyts.net/content/projects/Emc/Emc.png" />
        </p>
        <p>
E = m c² is a free utility that can check various sources for messages, then filter
and redistribute them. 
</p>
        <p>
A typical example is checking your mailbox and showing you a popup window if there
are new messages, but it goes far beyond that since it's fully extensible using plugins.
For example, you can check RSS files for new blog posts, monitor when a server comes
online or goes offline, play a soundfile when new messages arrive, send a summary
email, run a program, write to an RSS file, ... 
</p>
        <p>
Basically, you can make E = m c² do all you can think of! And it can do your laundry
too (Pro version only**)!
</p>
        <p>
What's new in this version?
</p>
        <ul>
          <li>
I'm also releasing the source code from now on (built on .NET 2.0 with Visual Studio
2005).</li>
          <li>
Added support for trigger plugins to provide a list of messages of their own when
they trigger. This allows non-pull scenarios to be supported as well (i.e. not only
receiving messages by "pulling" Source plugins, but "pushing" to deliver messages
from within a trigger immediately). 
</li>
          <li>
Added support for "hosted" plugins, which don't actively participate in the message
cycle but are just running in the context of E = m c². This means they don't handle
messages but they can still have their own settings and commands. This can be convenient
to host small pieces of functionality with settings that would otherwise require a
standalone application. 
</li>
          <li>
Duplicated the "Change Background" as a separate "hosted" plugin so you can also use
it as is, outside of the message cycle. 
</li>
          <li>
The "Change Background" plugins now support other background styles than just "stretch".
The new StretchedWithAspectRatio option retains the aspect ratio of the original image
while stretching it to fit the screen. 
</li>
          <li>
Added "Yahoo! Mail" plugin that retrieves messages from Yahoo! Mail (but you need
to make sure that your account is still using the "classic" user interface for this
to work). 
</li>
          <li>
Added "Network Changed" trigger, which triggers when the network changes (e.g. when
you plug in or out of a network). 
</li>
          <li>
Added "Debug" publisher, which writes messages to the Windows debug stream. 
</li>
          <li>
The "Viewer" can now have message styles to color rows depending on certain message
properties, e.g. the source of a message or its subject. 
</li>
          <li>
The "Viewer" can now be configured to have an initial window state, e.g. to make it
start as maximized. 
</li>
          <li>
The template processor can now also use reflected properties, so not just the built-in
tokens as before - e.g. $(Sender) - but also tokens that are taken from the value
of a property on the (optionally subclassed) message at runtime. This provides better
templating support for messages that are subclassed from the base EmcMessage class. 
</li>
          <li>
The "RSS Source" plugin now attempts to remember the read items between sessions of
the application. 
</li>
          <li>
The "RSS Publisher" plugin now also writes the message recipients to the RSS feed
so that a client also has access to the original message recipients. 
</li>
        </ul>
        <p>
You can find all information, screenshots, downloads, and even tutorials on writing
plugins at the dedicated website: <a href="http://jelle.druyts.net/emc/">http://jelle.druyts.net/emc/</a>. 
</p>
        <p>
Now I can continue working on the next version, which should turn out to be quite
interesting. I already have a number of features lined up and semi-implemented that
will take it to a next level. So I think that'll make it v3.0 and non-arguably the
most interesting download of 2008 <em>galaxywide</em>***.
</p>
        <p>
I'm even thinking of changing the name to something more meaningful and search-engine-friendly.
I don't want to keep steeling Google Love™ from my good friend Albert, you know...
So any suggestions would be welcome, and if yours makes it then you'll get a Pro version
for free**!
</p>
        <p style="FONT-SIZE: x-small">
* Usage information obtained by bribing a guy with a moustache who works at a local
internet provider and promised me the number of downloads was legit. 
<br />
** Ha ha! There isn't really a Pro version!<br />
*** I might be a bit biased.
</p>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=21aa7d3c-4363-4684-8be7-b7ff0d49be48" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Setting up Source Server for TFS Builds</title>
    <link rel="alternate" type="text/html" href="http://jelle.druyts.net/2007/12/09/SettingUpSourceServerForTFSBuilds.aspx" />
    <id>http://jelle.druyts.net/PermaLink.aspx?guid=64a4eff4-55d5-4669-a7bc-ebe1dcd591a6</id>
    <published>2007-12-09T10:16:12-08:00</published>
    <updated>2008-04-30T03:22:04.23825-07:00</updated>
    <category term="Blog" label="Blog" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog" />
    <category term="Blog/Programming" label="Blog/Programming" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming" />
    <category term="Blog/Programming/.NET" label="Blog/Programming/.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET" />
    <category term="Blog/Programming/.NET/VS.NET" label="Blog/Programming/.NET/VS.NET" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7c.NET%7cVS.NET" />
    <category term="Blog/Programming/TeamSystem" label="Blog/Programming/TeamSystem" scheme="http://jelle.druyts.net/CategoryView.aspx?category=Blog%7cProgramming%7cTeamSystem" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>[<a href="http://jelle.druyts.net/2008/04/30/UpdatedSettingUpSourceServerForTFSBuilds.aspx">Update
30/04/2008</a>] Fixed issue for Build Definition names that contain spaces.</em>
        </p>
        <p>
I've read about <a href="http://msdn.microsoft.com/msdnmag/issues/06/08/UseTheSource/default.aspx">symbol
servers and source servers</a> before (in John Robbins' excellent <a href="http://www.amazon.com/gp/product/0735622027/ref=s9_asin_title_1/104-9346732-5442324?pf_rd_m=ATVPDKIKX0DER&amp;pf_rd_s=center-2&amp;pf_rd_r=1VKRMDTB9NWV2YBQRDWA&amp;pf_rd_t=101&amp;pf_rd_p=278240301&amp;pf_rd_i=507846">Debugging
Microsoft .NET 2.0 Applications</a> book, for example, and also due to the recent
news that <a href="http://weblogs.asp.net/scottgu/archive/2007/10/03/releasing-the-source-code-for-the-net-framework-libraries.aspx">Visual
Studio 2008 will support source-code debugging of the .NET Framework Libraries</a>),
but never really got around to trying them out since they seemed pretty complex to
set up. However, I've recently set up a source server on a Team Foundation build server
(twice!), and my eyes have now gone wide open: anybody who references assemblies built
by those TFS build servers can now seamlessly debug them.
</p>
        <p>
When an assembly is "source server-enabled", the pdb file will contain the <strong>full
path </strong>and the <strong>exact version </strong>of the file <strong>in source
control </strong>that was used to build that assembly. If the debugger then enters
a method, Visual Studio automatically downloads that correct file, places it in a
local cache, and opens it for debugging. This is super sweet!
</p>
        <p>
Now the hard work was already done and <a href="http://tools.osherove.com/CoolTools/SourceServerSupportforTeamSystem/tabid/190/Default.aspx">published
by Roy Osherove</a>, but there were some extra steps to take if you wanted to integrate
this in a real Team Build (i.e. on the TFS build server instead of on a local machine)
and it also lacked some additional information to get everything working. So I put
together a full document that covers all aspects of setting up a source server, modifying
the Team Build script, configuring the project files, and finally configuring the
development machines.
</p>
        <p>
The full document (PDF) can be downloaded here, and you can read the one-page summary
that briefly covers the required steps below. I cannot recommend setting up a source
server enough, it's free and takes less than an hour if you simply follow the procedure,
and the advantages are - hopefully - obvious.
</p>
        <p>
          <a href="http://jelle.druyts.net/content/binary/Setting%20up%20Source%20Server%20for%20TFS%20Builds.pdf">Setting
up Source Server for TFS Builds.pdf (597 KB)</a>
        </p>
        <p>
Note that this procedure works for both TFS 2005 as TFS 2008.
</p>
        <p>
          <strong>Installing Source Server on the Build Server</strong>
        </p>
        <ul>
          <li>
Install the <a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx">Debugging
Tools for Windows</a> (including the full SDK) 
</li>
          <li>
Install Perl (e.g. <a href="http://www.activestate.com/Products/activeperl/">ActivePerl</a>) 
</li>
          <li>
Copy the TF.pm and TFIndex.cmd files from <a href="http://tools.osherove.com/CoolTools/SourceServerSupportforTeamSystem/tabid/190/Default.aspx">Roy
Osherove's "Source Server Support for Team System"</a> to "C:\Program Files\Debugging
Tools for Windows\sdk\srcsrv" 
</li>
          <li>
In the TFIndex.cmd file in that directory, change the last line to</li>
        </ul>
        <pre>@call "%~dp0SSIndex.cmd" -SYSTEM=TF <b>-SYMBOLS=%1</b> %*</pre>
        <ul>
          <li>
In the srcsrv.ini file in that directory, set MYSERVER to the exact URL of your Team
Foundation Server (Application Tier) 
</li>
          <li>
Add the full path to TF.exe (usually "C:\Program Files\Microsoft Visual Studio 8\Common7\IDE")
to the system's Path environment variable 
</li>
          <li>
Restart the Team Build Service</li>
        </ul>
        <b>Enabling Source Server in the Team Build Script</b>
        <ul>
          <li>
Add a new target to be run on "AfterCompile" that calls TFIndex.cmd:</li>
        </ul>
        <pre>&lt;Target Name="RunSourceServerIndexing"&gt;<br />
&lt;Exec Command="&amp;quot;C:\Program Files\Debugging Tools for Windows\sdk\srcsrv\TFIndex.cmd&amp;quot;
&amp;quot;$(BinariesRoot)&amp;quot;"<br />
        WorkingDirectory="$(SolutionRoot)" /&gt;
&lt;/Target&gt; &lt;Target Name="AfterCompile"<br />
        DependsOnTargets="RunSourceServerIndexing"
/&gt;</pre>
        <b>Configuring the Project Files</b>
        <ul>
          <li>
Set the Debug Info in Project Properties / Build / Advanced to "full" (Debug configuration)
or "pdb-only" (Release configuration)</li>
        </ul>
        <b>Configuring the Development Machines</b>
        <ul>
          <li>
In Visual Studio / Tools / Options / Debugging / General: check the "Enable source
server support" checkbox 
</li>
          <li>
Create a new text file named srcsrv.ini in "C:\Program Files\Microsoft Visual Studio
8\Common7\IDE" that contains the exact following text:</li>
        </ul>
        <pre>[trusted commands] 
cmd.exe /c TF.exe view</pre>
        <img width="0" height="0" src="http://jelle.druyts.net/aggbug.ashx?id=64a4eff4-55d5-4669-a7bc-ebe1dcd591a6" />
      </div>
    </content>
  </entry>
</feed>