In a previous note I showed using System.Transactions with the Longhorn transacted file system. That note had explicit calls to the Win32 services EnterTransactionScope and ExitTransactionScope. That worked to help show the example, but I want to share a small class that helps simplify the application code.
So, consider the following sample:
using System;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
namespace WindowsVistaSample
{
class ActiveKernelResourceRegion : IDisposable
{
[System.Runtime.InteropServices.DllImport("kernel32")]
internal static extern bool EnterTransactionScope();
[System.Runtime.InteropServices.DllImport("kernel32")]
internal static extern bool ExitTransactionScope();
private TransactionScope scope;
private bool enteredKernelAmbient = false;
private bool disposed = false;
public ActiveKernelResourceRegion()
{
if (Transaction.Current == null)
{
throw new InvalidOperationException
("KernelAmbient requires an existing ambient transaction");
}
this.scope = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions(),
EnterpriseServicesInteropOption.Full);
if (!EnterTransactionScope())
{
throw new TransactionException
("Unable to enter the kernel ambient region");
}
this.enteredKernelAmbient = true;
}
public void Dispose ()
{
if (!this.disposed)
{
if (this.enteredKernelAmbient)
{
this.enteredKernelAmbient = false;
if (!ExitTransactionScope())
{
throw new Exception
("Fatal error occurred attempting " +
"to exit a kernel ambient region");
}
}
if (this.scope != null)
{
this.scope.Complete();
this.scope.Dispose();
this.scope = null;
}
this.disposed = true;
}
}
}
}
This class is used to denote a region where the file and registry operations have been attached to the ambient System.Transactions transaction. The following code shows using it to include a file operation within an active TransactionScope:
using (TransactionScope scope = new TransactionScope())
{
using (new ActiveKernelResourceRegion ())
{
StreamWriter stream;
using (stream = File.CreateText(fileName1))
{
stream.WriteLine(content);
}
}
scope.Complete();
}
UPDATE: This approach is no longer appropriate as of the Vista RC update. See http://pluralsight.com/blogs/jimjohn/archive/2006/08/31/36819.aspx for more information.
Posted
Sep 13 2005, 06:46 PM
by
jim-johnson