November 2006 - Posts

Hi folks,

I'm happy to announce I've joined the INETA Europe Speakers Bureau recently, as a result of the Speaker Idol victory at TechEd: Developers 2006 earlier this month. You can read more information on See you at some speaking engagement in the near future? Thanks to Damir and André for taking care of this.

Don't worry, technical posts are coming up very soon again, starting tomorrow with some expression tree basics in C# 3.0. Keep watching! | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Can you predict what the following piece of batch script will produce (and why)? Tip: run it more than one time.

@echo off for %%f in (a,b,c) do ( echo 1 %%f 2 set x=x1 %%f x2 echo %x% )

Source: question at the TechEd 2006 IT Forum ATE. | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks


In the previous TxF related post you saw how to interact with the KTM in a very low level way through interop. Basically, we did deal with the transaction directly instead of relying on the System.Transactions namespace. In today's post we'll deal with the same use case, a transactional file delete, but this time using System.Transactions and the Distributed Transaction Coordinator (DTC). A little plumbing will need to be done, but as you'll see encapsulation comes to the rescue, allowing us to hide all nitty gritty details.

What we want to do

Let's take off by a trip to the promised land. This is excatly the kind of thing we want to do (or something similar):


using (TransactionScope tx = new TransactionScope()) { DeleteFile(file1); DeleteFile(file2); tx.Complete(); }
We even might want to make a transaction spanning across TxF and, for instance, SQL Server database operations. In short, we want the System.Transactions way of working. Let's see how we can do this.


Realizing our dream

On to the code. But before we do so, a small overview of what we have to do:

  1. Create some DeleteFile method (you might want to declare it as a static method in a File class, for instance in the namespace System.IO.TxF).
  2. In that method, see whether we are in a transaction scope or not (using Transaction.Current).
    • If we are running outside a transaction, you could do quite some things: you could create one (no!), you could throw an exception (maybe) or you could do a non-transacted file delete (our choice).
    • If a transaction is in flight, we need to derive the KTM transaction handle from it (which is the most tricky part) and use it to call the transacted file delete function.
  3. Call the DeleteFile method inside a TransactionScope to make it transactional.

Here's our DeleteFile method (cut-and-paste in the demo skeleton that will come next):


1 #region Transactional file operations 2 3 [DllImport("Kernel32.dll")] 4 static extern bool DeleteFileTransactedW([MarshalAs(UnmanagedType.LPWStr)]string file, IntPtr transaction); 5 6 [DllImport("Kernel32.dll")] 7 static extern bool CloseHandle(IntPtr handle); 8 9 static void DeleteFile(string file) 10 { 11 if (Transaction.Current != null) 12 { 13 IKernelTransaction tx = (IKernelTransaction)TransactionInterop.GetDtcTransaction(Transaction.Current); 14 IntPtr txh; 15 tx.GetHandle(out txh); 16 17 if (txh == IntPtr.Zero) 18 throw new Exception(); //Q-n-D 19 20 if (!DeleteFileTransactedW(file, txh)) 21 throw new Exception(); //Q-n-D 22 23 CloseHandle(txh); 24 } 25 else 26 { 27 File.Delete(file); 28 } 29 } 30 31 [ComImport] 32 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 33 [Guid("79427A2B-F895-40e0-BE79-B57DC82ED231")] 34 internal interface IKernelTransaction 35 { 36 void GetHandle([Out] out IntPtr handle); 37 } 38 39 #endregion
Let's take a look inside. Lines 3 and 4 are an old friend from our previous post. Inside the DeleteFile method, some interesting things are going on. First (11) we check whether or not we have a transaction in progress. If not (25-28) we just perform a non-transacted file delete (notice you might want to change this, e.g. to throw an exception). Otherwise, we do this:


  • Line 13 is a call to a much unknown TransactionInterop class that allows use to get the IDtcTransaction for a transaction (in our case the current one). We do cast this immediately to a IKernelTransaction (see further).
  • On line 15 we obtain the handle to the KTM kernel transaction. Notice we have to close it too (line 23) once we're done with it (we could do this in a better way by means of a SafeHandle kinda thing, which might be the subject of a later post).
  • Finally, the transacted file delete is done on line 20. If it fails, we fail the method by means of a (quick-n-dirty == Q-n-D) far-too-generic (:$) exception on line 21. In reality you'd analyze the last Win32 error and throw an appropriate exception. Anyhow, throwing an exception will cause the transaction to fail as a whole.

But what's that ugly thing on lines 31-37? In short, it a tlbimp-like thing derived from transact.h (see Windows SDK). Basically it's an import of a COM interface with a specified GUID, that derives from our pre-.NET friend IUnknown. Here's the original declaration (see how it maps to the C# equivalent declaration):


MIDL_INTERFACE("79427A2B-F895-40e0-BE79-B57DC82ED231") IKernelTransaction : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetHandle( /* [out] */ HANDLE *pHandle) = 0; };


The demo

Wanna see it in action? Here's the demo, mutated from the demo in the previous post. Just copy-past the code above in it:

using System; using System.Runtime.InteropServices; using System.IO; using System.Transactions; namespace TxF { class Program { static void Main(string[] args) { // // Demo setup. // string file1 = "c:\\temp\\txf1.txt"; string file2 = "c:\\temp\\txf2.txt"; using (StreamWriter sw = System.IO.File.CreateText(file1)) sw.WriteLine("Hello World"); using (StreamWriter sw = System.IO.File.CreateText(file2)) sw.WriteLine("Hello World"); // // Start the demo. // Console.WriteLine("Press <ENTER> to start the transaction."); Console.ReadLine(); // // Make it transacted. // using (TransactionScope tx = new TransactionScope()) { // // Delete the files (transacted). // DeleteFile(file1); DeleteFile(file2); // // Commit or rollback? // char c; do { Console.WriteLine("{0} {1}.", file1, System.IO.File.Exists(file1) ? "still exists" : "has vanished"); Console.WriteLine("{0} {1}.", file2, System.IO.File.Exists(file2) ? "still exists" : "has vanished"); Console.Write("Commit transaction (Y/N)? "); c = (char)Console.Read(); } while (c != 'Y' && c != 'y' && c != 'N' && c != 'n'); if (c == 'Y' || c == 'y') tx.Complete(); } } /* * REPLACE THIS #region Transactional file operations ... #endregion * */ } }
The demo script is the same as in the previous post, just see what happens if:
  • You commit the transaction.
  • You don't commit (= rollback) the transaction.
  • If you omit the TransactionScope.
  • If you lock any of the files prior to execution.
  • If you try to lock a file after DeleteFile has been called.

Use the locker.exe tool from the previous post to perform these experiments. Have fun!

Coming next on TxF adventures...

Even more transactional functions in a small starter System.IO.TxF namespace (step-by-step). Keep watching!

kick it on | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

A question on the discussion groups a couple of weeks ago: how to find out which processes are running managed code, and which version of the CLR? Here's the answer:

using System; using System.ComponentModel; using System.Diagnostics; class Proc { public static void Main() { Console.WriteLine("{0,-20} {1}", "Process Name ", ".NET version"); Console.WriteLine("{0,-20} {1}", "--------------------", "-------------"); foreach (Process p in Process.GetProcesses()) try { foreach (ProcessModule m in p.Modules) if (m.ModuleName.ToLower() == "mscorwks.dll") Console.WriteLine("{0,-20} {1}", p.ProcessName, m.FileVersionInfo.ProductVersion); } catch (Win32Exception) { } } }

On my machine it prints:

Process Name .NET version -------------------- ------------- WINWORD 2.0.50727.112 OUTLOOK 2.0.50727.112 dexplore 2.0.50727.112 WindowsLiveWriter 2.0.50727.112 devenv 2.0.50727.112 iexplore 2.0.50727.112 proc 2.0.50727.112

Notice the code can be improved quite a bit, as other exceptions might arise (InvalidOperationException when a process has exited during iteration; yes, this happens sometimes). So I only caught Win32Exception (lots of Access Denied errors can occur, especially on Windows Vista) to avoid the criticism "do never catch all" (which might be appropriate in here).

The cmdline equivalent of this is:

C:\temp>tasklist /FI "MODULES eq mscoree.dll" Image Name PID Session Name Session# Mem Usage ========================= ======== ================ =========== ============ iexplore.exe 4748 Console 1 42.092 K OUTLOOK.EXE 1524 Console 1 94.012 K devenv.exe 1424 Console 1 157.600 K WINWORD.EXE 7476 Console 1 44.288 K dexplore.exe 9376 Console 1 66.300 K WindowsLiveWriter.exe 11728 Console 1 48.128 K


C:\temp>tasklist /M mscoree.dll Image Name PID Modules ========================= ======== ============================================ iexplore.exe 4748 mscoree.dll OUTLOOK.EXE 1524 mscoree.dll devenv.exe 1424 mscoree.dll WINWORD.EXE 7476 mscoree.dll dexplore.exe 9376 mscoree.dll WindowsLiveWriter.exe 11728 mscoree.dll


kick it on | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

IT Forum 2006 has almost come to an end. I've just completed my ATE duties for Windows PowerShell; if you haven't downloaded it yet, go and take a look at The RTW version is available for XP SP2 and 2003 SP1. The RC2 version is available for Windows Vista.

Next, I'll be attending the last two sessions of the day. It's always nice to see Andrew Cheeseman And Team talk about their event network. For the last timeslot I'll take a look at some of the Windows Vista stuff on hardware.

Last day I attended a big session on Windows Vista Kernel Changes by Mark Russinovich (who has recently joined Microsoft, and was formerly one of the sysinternal guys). Mark gave a really nice overview of some of the most interesting changes to the Windows Vista kernel, which is also the foundation for Windows Longhorn Server. At the time of Vista SP1, the kernel versions will be synchronized again to make maintenance easier by just having to maintain one code base.

Needless to say the party last night by the Visual Studio 2005 Team Edition for Database Professionals (or shortway DataDude) folks was great. I didn't stay so long, but nevertheless a real recommendation.

Okay off to some sessions now. Stay tuned for some interesting (technical, at last) stuff coming up this weekend in "headless mode" and with daily blogging continuing next week as of Monday.


-Bart (who'll be flying back to Belgium tomorrow afternoon) | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Allrighty, kind of recoverd again; seems the BeFraLux country party last night had a healing effect. To be honest, I didn't know much of the people over there - I'm a developer after all - but lots of faces were familiar from MSDN/TechNet events in Belgium. So, we had some nice conversations about where all things come together: Windows PowerShell. Yeah baby, it's all over the place!

So right now I'm on the Windows PowerShell ATE booth (desk 28) with lots of great questions and feedback. Seems people start to love it and it's amazing to see people getting overwhelmed by all the power that gets unlocked by using the .NET Framework BCL underneath. Some of our great examples are:

PS C:\Users\Bart>([string](ipconfig | select-string IPv4)).substring(39) PS C:\Users\Bart> [int](get-wmiobject Win32_OperatingSystem).Version.Split(".")[2] 5600 PS C:\Users\Bart> $a = [UriBuilder]"" PS C:\Users\Bart> $a Fragment : Host : Password : foo Path : /dir Port : 21 Query : Scheme : ftp Uri : UserName : bar
Isn't this cool? Don't try to do the URL parsing yourself, just rely on the specalized classes in the .NET Framework. Still one hour to go over here on ATE before I'll attend some sessions. Tonight another party is on, from the Visual Studio team, which I'll visit together with the few U2U people who're still in Barcelona. Yeah, devs rule IT Forum :-) Should be | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Wednesday at TechEd 2006 IT Forum. Another big day for what the conference is concerned with great sessions on stuff like PowerShell, security, Longhorn Server AD, etc. Nevertheless, I got in late, still running on asperine. Tonight is the Belgian country drink, so I better can be up and running by tonight.

For my ATE duties, things have changed a bit. I'll be on the ATE booth for Windows PowerShell on Thursday and Friday for almost the whole day. There seem to be lots of questions on Windows PowerShell but we're lacking a dedicated booth for the technology, so you'll find us on desk 28 (Longhorn Server). | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

What a weird day this was. Woke up terribly sick and tired; guess the roundtrip through the city last weekend on top of the roof of a tourist bus is the evil (maybe the late night edition at Friday has to be blamed as well). As I mentioned earlier today, Bob's keynote kept me awake. But after that I had some pretty difficult times in the ATE to stay awake. Luckily there's that nice Spanish nurse in the cellar of the building that had some asperine that made me survive the afternoon. Never took much medicines before, but in this case it seemed to work pretty well. In the afternoon I attended (well, sort of) Rafal's session on holistic security as well as Steve Riley's one on system protection in Windows Vista, while doing some last minute work on my Speaker Idol demo. Have to say, this time I didn't win (which is kind of a relief as well; I'm not an IT pro after all). Apparently the judges liked the PowerShell-based PPT thing, but I went way over time (12 minutes instead of only 5) due to some technical issues with the Windows Live OneCare firewall that turned on all of a sudden (didn't have that issue last week) and, yes I have to admit, due to the little last-minute preparation. Maybe I shouldn't have blamed the product but that's I guess a developer's frustration when security turns against him. No further excuses :-). I want to thank the Belgian audience for the support and want to congratulate Andy Malone with his great presentation on Speech Recognition in Windows Vista. To all participants who'll be next: good luck and beware of the judges :-).

Oh, before I do forget, below you can find the "slides" I used. Just copy-paste into Windows PowerShell and press enter twice and there you go:

$ppt = { cls; write-host Windows PowerShell in 5 minutes; write-host *******************************; Read-Host; write-host * Next-generation command-line shell; write-host * Object-oriented; write-host write-host ??? = DIFFICULT ???; Read-Host; cls; write-host Discoverability; write-host ***************; Read-Host; write-host * Getting started; Read-Host; write-host * Demo - Scream for HELP: get-help; Read-Host; powershell; cls; write-host Commandlets and aliases; write-host ***********************; read-host; write-host * Cmdlet = Verb + Noun; read-host; write-host * get-process, get-childitem, clear-host, ...?; read-host; write-host * Enter aliases; Read-Host; write-host * Demo - get-command and get-alias; Read-Host; powershell; cls; write-host Object-orientation; write-host ******************; read-host; write-host * Developers, developers, developers?; read-host; write-host * NO!; read-host; write-host * What is an object?; write-host - Data = properties; write-host - Operations = methods; read-host; write-host * Discoverability: get-member read-host; write-host * Demo - The old way; write-host; cmd; cls; write-host Object-orientation; write-host ******************; write-host; write-host * Developers, developers, developers?; write-host; write-host * NO!; write-host; write-host * What is an object?; write-host - Data = properties; write-host - Operations = methods; write-host; write-host * Discoverability: get-member write-host; write-host * Demo - The old way; write-host; write-host * Demo - File information and file operations; Read-Host; powershell; cls; write-host Drives all the way; write-host ******************; read-host; write-host * What is a drive? [a-Z]:; read-host; write-host * Much more; write-host - HKLM:; write-host - Cert:; write-host - Variable:; write-host - Alias:; read-host; write-host * get-psdrive read-host; write-host * Demo - Dive into the registry; Read-Host; powershell; cls; write-host Conclusion; write-host **********; read-host; write-host * 5 commandlets to remember:; write-host - get-help; write-host - get-command; write-host - get-alias; write-host - get-member; write-host - get-psdrive; read-host; cls; write-host Q "&" A; write-host *****; write-host; write-host *; write-host *; read-host; $ie = new-object -Com internetexplorer.application; $ie.Navigate2(""); $ie.visible = 1; exit; }; &$ppt;
Enjoy! On to my ATE dutie right now, where I'll be the rest of the week at the indicated times (see previous post) to help you out with all possible PowerShell issues.

Cheers (Bart still in recovery mode)! | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Right, here we are again, up and running (well, sort of) at TechEd 2006 IT Forum. I'm actually feeling pretty sick today, guess the tourist bus roundtrip last weekend has been a bit too drafty. That's kind of the dark side of "Sunny Barcelona". Luckily, Bob Muglia was able to keep me alert during the keynote, which I found pretty interesting, even from a developer's perspective. Needless to say, Jeffrey Snover did a great job with his PowerShell baby once more, which just RTM'ed. Download now!

Later today I'll be trying to reload my batteries to get on stage this evening at 7PM for Speaker Idol once more. So if I do not run out of juice, come and see me. Guess a talk on Windows Vista Application Recovery would be right choice in my situation, but I'll tackle some IT related topic.

For my ATE duties, here's the schedule for the week:

  • Tuesday 14 Nov - 18:45 till 21:00 (I'll be at Speaker Idol between 19:00 and 20:00 however, but I'll try to compensate later this week).
  • Thursday 16 Nov - 10:00 till 13:00 (hopefully I can close the country party on Wednesday on time).
  • Friday 17 Nov - 10:00 till 13:00.

So, feel free to come and see me at desk 28 (Longhorn).

Cheers (Bart in recovery mode)! | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

What a busy weekend it has been. It al started on Friday evening with some nice dinner in the heart of Barcelona. Geeks all the way, so the topic of the talks shouldn't be too surprising :-). Nevertheless, it's amazing how fast Friday turns into Saturday, especially if you take a cab to Port Olimpic with people like Hans Verbeeck with some of his EMEA colleagues and a few guys from Redmond, responsible for TechEd US. We also met Tom Mertens finding his way back to the hotel after spending an evening with Wim and Wim visiting Parc Guell. Luckily bars close at 5 AM in the morning, otherwise chances were high Hans didn't make it in time for his plane in the morning :-). Btw, congratulations to Hans' daughter for her 8th anniversary. So, at the time metro trains started to run again, I found myself walking through the city to my hotel where I arrived somewhere around 6:30 AM. Needless to say I overslept and missed the breakfast :$.

Saturday noon: time to awake the tourist in me. It's the third time (previously TechEd 2003, IT Forum 2005) I'm in Barcelona, but the first time I had the time to explore the city (finally!). So I did with a ticket for the touristic bus that goes around the city. On Saturday I visited the Sagrada Familia (where I also found a pretty good restaurant for a nice pizza, my favorite tourist food) and Parc Guell (I'll post some photos somewhere online when I'm back at home). TechEd certainly is in the air (even in the weekend it is) since a couple of TechEd t-shirts appeared on several places in the park :-). If you visit Barcelona some time, these are two places you should have seen. Another popular place where the bus stops is FC Barcelona, but I skipped that one due to my low sports interest.

Sunday, another city exploration day. This time I took the bus for the Southern route, driving to Plaça d'Espanya and on to Montjuïc. It was a pretty long climb to the top of the hill to visit the castle and the Olympic village from 1992 when the Olympic Games took place in Barcelona. If you decide to make the walk to the top, I'd recommend you to take some drinks with you. Things are not always as they look: imagine a nice terrace on the top of the hill without service :s. As worse as things can get, the regular entrance to the castle seemed to be blocked due to construction works, so I had to walk around the castle in the opposite direction. It was only when I arrived at my destination (i.e. on top of the castle), I saw the regular entrance being reachable by a very small path. After all, I'm happy to have taken the long way, which had a great panoramic view on the Mediterrean Sea. The next stops of the bus were the World Trace Center, Port Vell, Port Olimpic (where I took a photo of the infamous pubs we visited throughout the week), the Poblenou Cemetery (the oldest in Barcelona with great sculptures, worth the visit), the Parc de la Ciutadella and Barri Gòtic (which I still have to visit next Saturday before catching my flight to Brussels). And I has been proven once more: it's a small world we live in. During my walk back to the hotel, passing by Palau de Musica, I met Jan Tielens and his wife.

On to another week in Barcelona for TechEd 2006 IT Forum. You can find me on the ATE booth for Windows PowerShell once more (desk 28) on the following times:

  • Tuesday 14 November 2006 - 18:45 to 21:00 (during the exhibition hall opening reception, I'll be off for one hour to Speaker Idol once more)
  • Thursday 16 November 2006 - 10:00 to 13:00
  • Friday 17 November 2006 - 10:00 to 13:00

Today I'll be following the pre-conference on SQL Server 2005 Always On Technologies. I'll report about it later today. | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts « Previous page - Next page »