September 2004 Entries

Ok, normally I don't like RPGs very much, but I picked up Fable when it came out and am probably like 1/4 of the way into the storyline and I'm really liking it so far. The story is great so far and the level of character customization is amazing. I'm playing the game as a saint so far, in fact I've already got a halo over my head (if I were evil I'd have horns). My only real complaints revolve around the control scheme. I consider myself pretty proficient at mastering game controls, but so far I'm still fumbling with Fable. Locking on to enemies (left trigger) is pretty poorly implemented. You lose the lock if you run around too much and it's really tough to shift the lock between enemies, so when you're fighting off swarms of enemies and you knock one down, there's no easy way to immediately target the next one without just turning yourself to face them precisely. Next, I hate that I have to hold the Y button to block. It would have made more sense to hold the left trigger to block and use the Y button to cycle the enemy lock on instead. Then there's the whole right trigger modifier to bring up the spells list which you then have to cycle through by pressing the very same button you would to block! You're holding so many things down in the middle of combat that your brain has a hard time keeping track. Hopefully I'll master it eventually, but it's definitely one of the toughest setups I've played in a while.

posted Wednesday, September 29, 2004 3:23 PM | Comments | Filed Under [ Personal ]
Never in my life have I laughed so hard in a movie theater. Never in my life have I seen an entire audience laugh so hard in a movie theater. Instant classic. You gotta go see it.
posted Sunday, September 26, 2004 11:10 AM | Comments | Filed Under [ Personal ]

Hopefully things have cooled enough since the cut-back announcement to ask this question without everyone getting all upset or starting yet another thread of FUD, so here goes:

It's been quite some time since the general development community has seen a refreshed drop of Longhorn... I believe WinHec was the last? Obviously things are a little different now given that WinFX and Avalon (not so much Indigo) have to be implemented on an “older” kernel. First off, it would be nice to know when we can expect to see an official list of what sub-features did or didn't make the cut. Second, when we can expect to see the first drop of those bits? :)

I would imagine the first drop needs to be sometime within this year if they really hope to hit a Q1/Q2-2006 release. I realize things are pretty crazy and some of this stuff probably still hasn't been completely figured out. So, to be clear, I'm not asking for an actually list or bits to be posted tomorrow or anything, just an ETA. If anyone out there from MS could just give us eager devs heads up, that would rock... and I'm sure I'm not the only one who would appreciate it. ;)

posted Thursday, September 23, 2004 5:52 PM | Comments | Filed Under [ WinFx/Vista ]

I just entered a suggestion for the Whidbey .NET Framework. It has to do with adding a Disposed event to the SqlDataReader. Every other major class (SqlConnection, SqlCommand, SqlDataAdapter, etc.) in the System.Data.SqlClient namespace has a this event, so why not SqlDataReader. My personal reason for having it is that I have a data access layer which I'd like to hand SqlDataReader instances out from and I'd like to be able to track the disposal of those instances.

If you think this is a good or bad idea or have any other suggestions, head over to LadyBug and make yourself heard.

posted Wednesday, September 22, 2004 7:59 PM | Comments | Filed Under [ .NET ]

Ok, so if you read this previous post, you'd know that I ran into a problem with ConfigXmlDocument not setting the BaseURI property making resolution of relative URIs within the document completely unpredictable and utterly useless. I really wanted it to work and knew there had to be a way, so I fgured out the following workaround (aka hack).

public sealed class HackedConfigurationNodeReader : XmlNodeReader
{
    #region Fields

    private string configurationFilePath;

    #endregion

    #region Constructors

    public HackedConfigurationNodeReader(string configurationFilePath, XmlNode configurationNode) : base(configurationNode)
    {
        this.configurationFilePath = configurationFilePath;
    }

    #endregion

    #region Base class overrides

    public override string BaseURI
    {
        get
        {
            return this.configurationFilePath
        }
    }

    #endregion
}

Now, all you need to do inside your IConfigurationSectionHandler::Create override is the following:

public object Create(object parent, object configContext, XmlNode sectionNode)
{
    // HACK: If configuration XML document's BaseURI is not set, use our hacked reader
    if(sectionNode.BaseURI.Length == 0)
    {
        reader = new HackedConfigurationNodeReader(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, sectionNode);
    }
    else
    {
        reader = new XmlNodeReader(sectionNode);
    }

    // Now pass the reader on to some class that expects a BaseURI for resolving relative URIs
    SomeXmlReadingObject object = new SomeXmlReadingObject();
    object.ReadXml(reader);
 }

The key here was that I want my SomeXmlReadingObject instance to be able to parse XML with relative URIs from a configuration section the same as it would parse XML from any other mechanism that passed it an XmlReader.

posted Monday, September 20, 2004 11:24 AM | Comments | Filed Under [ .NET ]

I've been an MVP since the early J++ days (1997'ish?). Then when .NET came along I was transitioned to the generic .NET Group and most recently pigeon holed into the C# Group. Unfortunately with all the “real” work I've been doing these past six months or so I just haven't had as much time to commit to the community. Only recently have I picked back up with weblogging and answering questions over on the DevelopMentor .NET Mailing Lists. There's just a ton of people competing for MVP status these days, which is great for the community, but bad for me since I've had to relenquish my status for now.

It was an awesome run and I want to extend a special “thank you” my MVP lead Rafael Munoz for all his hard work in keeping us all happy and connected. Hopefully I'll be back next year, perhaps this time as a Longhorn technology MVP (e.g. WinFX, Avalon, etc). :)

posted Thursday, September 16, 2004 5:42 PM | Comments | Filed Under [ Personal ]

Here's a missing piece of functionality that's frustrating me right now:

Basically, XmlDocument has a virtual property called BaseURI that subclasses can override to provide the base URI (go figure) from where the XmlDocument instance was loaded. In a normal XmlDocment, if you call the Load override specifying the “filename” parameter, it will set it's BaseURI to that. Also, if you Load the instance from an XmlReader that has it's BaseURI set it will inherit that. Anyway, my point is, the support is there in the base XmlDocument class.

Now we come to ConfigXmlDocument, which subclasses XmlDocument to provide special behavior for loading .NET application configuration files. Guess what it doesn't populate? You got it: BaseURI.

Next imagine you write a custom configuration section handler that parses an XML fragment inside of the configuration document and wants to allow people to use relative paths within the definition of that fragment. Now guess what the paths become relative to: the assembly of the configuration section handler.

So I've written a library which is now being used inside of an ASP.NET application. While the web.config is in the root of that application, people have to counter intuitively make any relative paths inside of that configuration section fragment relative to the /bin directory as opposed to the root. FWIW, the same thing happens with any Console and WinForms applications as well. Frustrating to say the least.

I'm going to check if this has been remedied in Whidbey and, if not, post a request to LadyBug to get it done. I see no reason why this should not be implemented.

Update:

I tested it in Whidbey and the results are unfortunately the same. I have submitted a bug, so if you find this important go ahead and vote for it.

posted Thursday, September 16, 2004 11:03 AM | Comments | Filed Under [ .NET ]
I'm selling my Toshiba Satellite P25-S607 over on eBay. It's a great machine and less than a year old. In fact, it's still under the original warranty! I loved that thing... actually I loved it so much that the reason I'm selling it is because I picked up the newer P25-S676 model.  It's basically the exactly same thing except for your standard upgrades in processor speed, storage devices and connectivity. These laptops make excellent all in one computers. I don't even have a desktop at home or at work anymore, I just carry this thing back and forth.
posted Thursday, September 16, 2004 9:14 AM | Comments | Filed Under [ Personal ]

This has got to be the best article/interview News.com has ever posted. I'm a huge MotoGP fan since motorcycle road racing is my biggest hobby, but I also watch F1 from time to time. MotoGP uses the same kind of technology to track every twitch the bike/rider ever makes. What's amazing is, when there's a crash they can pin point exactly what went wrong at that point in time. Did the rider apply too much throttle? Too much brake? Shift into the wrong gear? Or did the bike's suspension compress just a little too much?

It's absolutely amazing how far the technology in these two sports has come since computers started getting involved. The best part of it all is that everything they learn out there on the track eventually trickles down in some way to the consumer version of the car/motorcycle.

posted Friday, September 03, 2004 10:54 AM | Comments | Filed Under [ Personal ]

Ok, this is pretty crazy. I'm on XPSP2 and I've entered a ServiceDomain with a ServiceConfig that requires transactions with an IsolationLevel of Serializable. Now, I've done this a million times before and it works no problem. In the specific scenario I'm dealing with now, I'm seeing something completely insane. I've constructed a SqlConnection and I'm getting ready to Open it. Up until I call Open ContextUtil.IsInTransaction is true. Now I step over the call to Open and *bam* I've lost my COM+ context. ContextUtil.IsInTransaction is now false and any attempt to SetComplete or SetAbort throws:

System.Runtime.InteropServices.COMException (0x8004E004): There is no MTS object context at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo) at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode) at System.EnterpriseServices.Thunk.ContextThunk.SetComplete() at System.EnterpriseServices.ContextUtil.SetComplete()

No exceptions are being thrown from within the call to Open and I can run another project that does the same transaction/connection logic to the same SQL server instance, which is just a local instance on my dev box anyway, and use distributed transactions there just fine. Therefore I know my MSDTC is properly configured and working.

I've cross-posted this to the ADVANCED DOTNET list that DM hosts. Hopefully I'll get an answer from someone soon, 'cause I'm completely perplexed by this one.

Update:

Ok, so I dug a little deeper. I found out exactly where inside of SqlConnection::Open that my context is being blown away. Have a look at this:

system.enterpriseservices.dll!System.EnterpriseServices.Platform.Initialize() + 0x117 bytes 
  system.enterpriseservices.dll!System.EnterpriseServices.Platform.get_W2K() + 0x9 bytes 
  system.enterpriseservices.dll!System.EnterpriseServices.ResourcePool.ResourcePool(System.EnterpriseServices.ResourcePool.TransactionEndDelegate cb = {System.EnterpriseServices.ResourcePool.TransactionEndDelegate}) + 0x1b bytes 
  system.data.dll!System.Data.SqlClient.ConnectionPool.CreateResourcePool() + 0x40 bytes 
  system.data.dll!System.Data.SqlClient.ConnectionPool.ConnectionPool(System.Data.SqlClient.DefaultPoolControl ctrl = {System.Data.SqlClient.SqlConnectionPoolControl}) + 0x1c2 bytes 
  system.data.dll!System.Data.SqlClient.PoolManager.FindOrCreatePool(System.Data.SqlClient.DefaultPoolControl ctrl = {System.Data.SqlClient.SqlConnectionPoolControl}, int SID = 2066800) + 0xb8 bytes 
  system.data.dll!System.Data.SqlClient.SqlConnectionPoolManager.GetPooledConnection(System.Data.SqlClient.SqlConnectionString options = {System.Data.SqlClient.SqlConnectionString}, bool isInTransaction = false) + 0x141 bytes 
  system.data.dll!System.Data.SqlClient.SqlConnection.Open() + 0xce bytes 

So what this looks like is, even though I've already entered a ServiceDomain prior to opening the SqlConnection, this particular code path somehow reinitializes .NET's enterprise services layer whacking the current COM+ state. Can you say BUG!? :\

Well I'll go ahead and submit this as a bug, but the workaround would seem to be to open a dummy SqlConnection at the very beginning of your application (perhaps for each distinct connection string since each one creates a new pool??) to force this scenario to happen so that future calls to open a connection, which may actually need the connection to be hooked up, do not have to run through this code path.

posted Wednesday, September 01, 2004 3:53 PM | Comments | Filed Under [ .NET ]