Blog

Singapore

Last month, on September 13th to 17th, I attended the 36th International Conference on Very Large Databases (VLDB 2010) in Singapore, to present a paper at the Ph.D. workshop.

Not only was this the first time I've been to such a large international conference (which was very interesting because it allowed me to talk to a lot of experts in my field and see what other people are doing), it was also the first time I ever visited Singapore.

Fortunately, I was able to get some time for sightseeing, and these pictures are the result. :)

Show images (129)

Categories: University, Personal
Posted on: 2010-10-16 08:55 UTC. Show comments (5)

FormatC 2.0 (syntax highlighting) now available

With the release of .Net 4.0 I have updated the FormatC syntax highlighter (used for all code samples on ookii.org) to support new keywords introduced in Visual Basic 10.0 and C# 4.0.

That's not the only update, however. FormatC 2.0 also has the ability to escape contextual keywords (previously, it would treat them as keywords regardless of the context), type name highlighting support for Visual Basic and improved XML literal support in Visual Basic.

PowerShell support is also improved; FormatC will try to use the parser included with PowerShell 2.0 to parse the code. Unfortunately, this web server does not have PowerShell 2.0 installed, so the online version of the highlighter will still use regular expressions to highlight PowerShell code.

If you have any feedback about FormatC, please leave it as a comment on this blog post.

Sample C# code highlighted using FormatC:

public static int SumAuthorPrices(IEnumerable<Book> books, string author)
{
    if( books == null )
        throw new ArgumentNullException("books");

    return (from b in books
            where b.Author == author
            select b.Price).Sum();
}

Sample Visual Basic code highlighted using FormatC:

Public Shared Function ConvertToXml(ByVal books As IEnumerable(Of Book)) As XDocument
    If books Is Nothing Then
        Throw New ArgumentNullException("books")
    End If

    Return <?xml version="1.0"?>
           <Books>
               <%= From b In Books
                   Select <Book Author=<%= b.Author %> Price=<%= b.Price %>>
                              <%= b.Title %>
                          </Book> %>
           </Books>
End Function

Sample XML code highlighted using FormatC:

<?xml version="1.0"?>
<Books>
  <Book Author="Peter F. Hamilton" Price="18.99">
    The Evolutionary Void
  </Book>
</Books>

Sample T-SQL code highlighted using FormatC:

SELECT title, author, publisherName FROM Books b
  INNER JOIN Publisher p
  ON b.publisherId = p.id
WHERE b.price >= 10

Sample PowerShell code highlighted using FormatC (this used the parser-based method, not regular expressions):

foreach ($file in Get-ChildItem)
{
    if ($file.Length -gt 100kb) 
    {
        Write-Host -ForegroundColor Green $file
        Write-Host $file.Length
        Write-Host $file.LastAccessTime
    }
}

Categories: Software, Programming
Posted on: 2010-08-07 05:23 UTC. Show comments (1)

Opening files via IDropTarget in .Net

A while ago, Raymond Chen wrote about the mechanism for using IDropTarget to receive a list of files to open.

The DropTarget method provides you with an alternative way to register a verb for a file type (i.e. a right-click context menu option). The other alternatives are to receive the files via the command line or via DDE. Since DDE is deprecated, the DropTarget method is specifically meant to replace that.

The primary reason you might want to use this method is if you want to open multiple files in the same application instance. If you select multiple files at once in Explorer and then right-click them and select your custom option, if you used the traditional command line method, your application would be launched multiple times. With the DropTarget method, the application is launched only once and that one instance receives all the files. What’s more, if your application is already running the existing instance will receive the files.

Raymond provided sample code for how to use this method in C++, but what if you want to do this in .Net? Fortunately, it’s relatively easy to do.

Although both Windows Forms and Windows Presentation Foundation have support for drag and drop and probably implement IDragDrop somewhere internally, we need to have access to an implementation we can expose as a COM local server so we cannot use this. And although Windows Forms exposes an IDropTarget interface, this interface does not match the COM interface we need so it’s also of no use to us.

So the first thing we need is the COM IDropTarget interface. I couldn’t find any type library we could import in .Net, so we’ll define the interface manually. Fortunately, it’s not very big so this is pretty easy.

using System.Drawing;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00000122-0000-0000-C000-000000000046")] // This is the value of IID_IDropTarget from the Platform SDK.
[ComImport]
interface IDropTarget
{
    void DragEnter([In] IDataObject dataObject, [In] uint keyState, [In] Point pt, [In, Out] ref uint effect);
    void DragOver([In] uint keyState, [In] Point pt, [In, Out] ref uint effect);
    void DragLeave();
    void Drop([In] IDataObject dataObject, [In] uint keyState, [In] Point pt, [In, Out] ref uint effect);
}

Since this code will only ever be used for the shell DropTarget method, and not for actual dragging and dropping, I’ve not bothered to use proper enumerations for keyState and effect, because we won’t use those arguments. Also note I’m making use of the IDataObject COM interface from the System.Runtime.InteropServices.ComTypes namespace.

Besides the COM interface, we’ll also need two define two PInvoke methods as well as a constant for the data format we’ll use.

using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

static class NativeMethods
{
    public const int CF_HDROP = 15;

    [DllImport("shell32.dll", CharSet=CharSet.Unicode)]
    public static extern int DragQueryFile(HandleRef hDrop, int iFile, [Out] StringBuilder lpszFile, int cch);

    [DllImport("ole32.dll")]
    internal static extern void ReleaseStgMedium(ref STGMEDIUM medium);
}

Here we’re using the STGMEDIUM structure, also defined in the System.Runtime.InteropServices.ComTypes namespace.

Next, we have to create a class that implements this interface. The only members the shell ever calls are DragEnter and Drop, and the only one we’ll actually need is Drop, so we’ll leave the rest empty.

using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;

[ComVisible(true)]
[Guid("your-guid-here")]
public class MyDropTarget : IDropTarget
{
    public void Drop(IDataObject dataObject, uint keyState, System.Drawing.Point pt, ref uint effect)
    {
        FORMATETC format = new FORMATETC()
        {
            cfFormat = NativeMethods.CF_HDROP,
            dwAspect = DVASPECT.DVASPECT_CONTENT,
            tymed = TYMED.TYMED_HGLOBAL
        };
        STGMEDIUM medium;
        string[] files;
        dataObject.GetData(ref format, out medium);
        try
        {
            IntPtr dropHandle = medium.unionmember;
            int fileCount = NativeMethods.DragQueryFile(new HandleRef(this, dropHandle), -1, null, 0);
            files = new string[fileCount];
            for( int x = 0; x < fileCount; ++x )
            {
                int size = NativeMethods.DragQueryFile(new HandleRef(this, dropHandle), x, null, 0);
                if( size > 0 )
                {
                    StringBuilder fileName = new StringBuilder(size + 1);
                    if( NativeMethods.DragQueryFile(new HandleRef(this, dropHandle), x, fileName, fileName.Capacity) > 0 )
                        files[x] = fileName.ToString();
                }
            }
        }
        finally
        {
            NativeMethods.ReleaseStgMedium(ref medium);
        }

        // Do something with the files here.
    }

    public void DragEnter(System.Runtime.InteropServices.ComTypes.IDataObject dataObject, uint keyState, System.Drawing.Point pt, ref uint effect)
    {
    }

    public void DragOver(uint keyState, System.Drawing.Point pt, ref uint effect)
    {
    }

    public void DragLeave()
    {
    }
}

This code simply retrieves the files we were passed and stores them in an array. It’s up to you to do something interesting with them afterwards (and I’d recommend not doing any further processing on the thread that called Drop because you’ll make the shell wait for your drop handler to complete).

Finally, you need to put some special code in your Main method to make the COM server available to other applications while your application is running.

static void Main(string[] args)
{
    RegistrationServices reg = new RegistrationServices();
    // this is the equivalent to CoRegisterClassObject in Win32
    int cookie = reg.RegisterTypeForComClients(typeof(MyDropTarget), RegistrationClassContext.LocalServer, RegistrationConnectionType.MultipleUse);
    try
    {
        if( args.Length > 0 &&
            !(string.Equals(args[0], "-embedding", StringComparison.OrdinalIgnoreCase) ||
              string.Equals(args[0], "/embedding", StringComparison.OrdinalIgnoreCase)) )
        {
            // If your application was launched by COM as a local server, it'll specify the -Embedding or /Embedding switch.
            // If the -embedding argument was not specified, we should process the command line normally
            OpenFilesFromCommandLine(args);
        }

        // Run your application, e.g. by using Application.Run in Windows Forms.
    }
    finally
    {
        reg.UnregisterTypeForComClients(cookie);
    }
}

Now all that’s left to do is to create the relevant registry entries, which Raymond already covered and which is not any different for .Net:

[HKCR\CLSID\{your-guid-here}\LocalServer32]
@="C:\\Path\\To\\Your\\.Net\\App.exe"

[HKCR\txtfile\shell\yourverb\DropTarget]
"Clsid"="{your-guid-here}"

This registers your application as a context-menu item for text files. Change txtfile to the appropriate value for the file type you wish to handle. Note that you can also register per-user by putting these keys in HKCU\Software\Classes rather than HKCR.

Note that you shouldn’t register your assembly using regasm.exe. Regasm.exe can only be used to register in-process COM servers, not local servers. It also registers your object via the .Net COM InterOp proxy DLL which isn’t necessary for out-of-process COM.

I’ve created a small sample that shows you how to use these techniques in a GUI application: download the ShellDropTargetSample here.

That sample is a .Net 4.0 WPF application created in Visual Studio 2010, but the techniques discussed here are also usable with older versions of .Net and with Windows Forms and console applications.

Note that the sample registers the COM object and parses the command line in App.OnStartUp (in the App.xaml.cs file) rather than the Main method.

Categories: Programming
Posted on: 2010-07-03 10:06 UTC. Show comments (13)

Command line argument parser for .Net

Every developer has at some point in time written code to interpret the command line arguments of their program. Of course, I'm no exception. When I was recently in need of a quick way to parse the arguments for a whole bunch of different scenarios, I decided to go the extra mile and just write a generalised class that would let you easily define what arguments you want and then parses it for you.

I've now made that class available, in the Ookii.CommandLine class library.

It's very easy to use. Just create a class, and the constructor parameters of that class, as well as properties marked with a special attribute, will make up the command line arguments of your application. It can even create help text for the command line usage of your application.

More information, documentation, downloads and samples at the link above.

Yeah, I know there's a lot of similar stuff out there already. Now there's one more. :)

Categories: Programming
Posted on: 2009-09-06 08:59 UTC. Show comments (6)

Mt. Fuji climbing

It has been a long time since I posted anything about a trip here, but now it's time I do so. Last weekend, the 22nd and 23rd of August, I along with six friends climbed Mt. Fuji.

We set off on Saturday, leaving Tokyo at 12:40 by bus from Shinjuku, and we arrived at the fifth station of the Kawaguchiko trail (at an altitude of 2305 meters) around 17:00. After spending some time getting used to the thinner air, we started climbing around 18:00. Our schedule had us on the summit some time around 2:00 in the morning, but that was hopelessly optimistic. The climb was very exhausting, and I'm not exactly in the best shape, so it took us somewhat longer. The large number of people caused the occasional "traffic jam" which also caused a lot of delay. It's really unbelievable how crowded that mountain is. It's worse than Shinjuku station.

Our goal was of course to reach the summit before sunrise at 5:00 in the morning, but unfortunately we fell short of that goal by about 300 meters (distance, not altitude). Probably a good thing, in retrospect, since it appeared to be much more cloudy on the actual summit so we probably got a better view from where we were. After sunrise, we continued to the summit. Unfortunately, because many people had paused to watch the sunrise, an enormous queue had formed leading up, so eventually we were at the summit around 6:30. Once there, we took some rest, ate some food (despite the high prices I did buy some noodles, just to have something hot to eat, as it was very cold on the summit). Although thoroughly exhausted, we were all glad we made it.

Here's where things started to go wrong, though. For one thing, we hadn't all made it to the summit at the same time, so we were already separated. I was with only two others when we started our descent, and unfortunately we took the wrong trail back down (the trail down was not supposed to be the same one we took up, but we still took the wrong one). Despite the fact that there's signs every twenty meters or so, none of us noticed it was the wrong trail until we were all the way at the bottom. While we did arrive at a fifth station, it was the wrong fifth station. Of course, the others who went down separately did take the right trail so we couldn't meet with them. And because everybody managed to have dead cell phone batteries at the same time, we couldn't even contact each other to try and sort things out. So we could only go back to Tokyo on our own and hope the others did the same (which of course they did). It all worked out in the end, but it was a pretty stupid feeling when we realised we were at the wrong location after climbing all that way down.

But no matter how grueling the journey (especially the wind and the dust on the way down were very bad), and no matter the mistake with the descent, I'm still glad we did it, and I'm very happy I made it, of course. In fact, I still have trouble believing it. It's the longest single climb I've ever done, and the highest I've ever been (3776 meters at the summit, prior to this the highest I'd been was 3400m in the Sierra Nevada in Spain). The beautiful sunrise (the pictures don't do it justice, really), and the sheer satisfaction of reaching the goal, make it worth it.

Enjoy the pictures!

Show images (47)

Categories: Personal, Japan
Posted on: 2009-08-30 09:11 UTC. Show comments (4)

Latest posts

Categories

Archive

Syndication

RSS Subscribe

;