Thursday, December 30, 2004

File Sharing Via RDP

This one might fall into the “I'm the last guy to find this out” category, but given that I'm a regular user of Remote Desktop and I didn't notice it until a friend pointed it out, I'm guessing that others haven't discovered this little gem, either.


If you're connecting via the Remote Desktop Client to another machine, and you want to be able to copy files from here to there, open up “Options” and under “Local Resources” check “Disk Drives”, like so:



Then, when you connect to the remote computer, the remote computer will be able to see your local drives as if they were on the remote computer, making it trivial to drag and drop files via Explorer.

Tuesday, December 14, 2004

I'm Pro-xs:choice

There's been lots of debate about use of DataSets with web services. The issue is interoperability: the default WSDL representation of a DataSet is an arbitrary schema followed by arbitrary XML. That's just a bit on the loose side for most toolkits to deal with in the general case. However, one use case that drives the desire to use a DataSet in the first place is that the type of data to be returned is not known precisely until runtime. Lately, I discovered yet another corner of XmlSerializer that helps me deal with some of these situations without having to resort to using a DataSet.


It turns out that sometimes, although you don't know the exact type of data you'll be returning, you do know that it's going to be one of a known set of types. This is particularly common when you're returning the results of a database query: you might know that all your columns are either strings, booleans, integers, dates, or floating point numbers. If that's the case, there's an XML schema construct that allows you to say, “I want to have one of the following elements appear here.” It's called <xs:choice>, and here's a schema fragment that demonstrates its use:



<xs:element name=“item“>
  <xs:complexType>
    <xs:choice>
      <xs:element minOccurs=“1“ maxOccurs=“1“ name=“string“ type=“xs:string“ />
      <xs:element minOccurs=“1“ maxOccurs=“1“ name=“integer“ type=“xs:int“ />
      <xs:element minOccurs=“1“ maxOccurs=“1“ name=“boolean“ type=“xs:boolean“ />
      <xs:element minOccurs=“1“ maxOccurs=“1“ name=“date“ type=“xs:dateTime“ />
      <xs:element minOccurs=“1“ maxOccurs=“1“ name=“float“ type=“xs:float“ />
    </xs:choice>
  </xs:complexType>
</xs:element>


What this schema means is that when an “item” element appears, it must have as a child exactly one of the elements <string>, <integer>, <boolean>, <date>, or <float>. Further, if the child element is <string>, the contents of that element must be a string. But if the child element is <integer>, then the contents must be an integer, and so on and so forth. It's a reasonably “normal“ bit of schema, and while I have no idea what the support in various non-.NET toolkits looks like, support for it is a lot more likely to exist than for the vagaries of DataSet.


From an XML standpoint, this is a pretty nice thing. It lets us express exactly what we want, namely, that we'll tell you at runtime what our choice for the type of the data is. Where this gets really great is that it's supported by System.Xml.Serialization, which powers the ASP.NET Web Services stack.


Here's how it maps: you define a class with the usual attributes from the System.Xml.Serialization namespace. But when you get to the element that you want to represent as an <xs:choice>, you simply use more than one [XmlElement] attribute, and you use the overload that lets you specify a type. Here's what I mean:


[XmlRoot(”item”)]
public class Item
{
  private object value; 

  [XmlElement(“string“, typeof(string))]
  [XmlElement(“integer“, typeof(int))]
  [XmlElement(“boolean“, typeof(bool))]
  [XmlElement(“date“, typeof(DateTime))]
  [XmlElement(“float“, typeof(float))]
  public object Value
  {
    get { return value; }
    set { this.value = value; }
  }
}


When the serializer encounters this type during either serialization or deserialization, it will use the attributes to control the mapping between element names and .NET types. Which is to say, when the Value is a float, you'll get <float>, when the Value is string, you'll get a <string>, and (better still) vice versa! You have to do a type test and typecast at the other end, like this:


if (foo.Value is string) { DealWithString((string) foo.Value); }
else if (foo.value is float) { DealWithFloat((float) foo.Value); }
// etc.


But big deal. :)


By itself, this is a fairly powerful feature. And there's still more we can do, but I think I'll stop this entry now while this entry is still reasonably short. More later.

Thursday, December 9, 2004

A Sad Day for Metal

I'm a fan of heavy metal music, although usually more specifically progressive heavy metal. Nevertheless, I enjoy straight-ahead, ass-kicking, hard-core metal quite a bit, and they don't come much harder core than Pantera. Thus, I was saddened to hear that Dimebag Darrell, their lead guitarist, was fatally shot while performing with his new band Damageplan last night. At this time, it's unclear whether his brother Vinnie Paul (formerly Pantera's drummer) was also shot, and if shot, whether he was killed. I certainly hope not for the sake of their family.


Dimebag was a huge influence on an entire generation of metal and nonmetal musicians. It's not unfair to compare the impact of his death on the musicians I most enjoy to that of the death of John Lennon on his generation...especially when you realize that Lennon was also killed on December 8th.

Wednesday, December 8, 2004

Tabs Are Evil

For about the 10,000th time today, I opened a file that looks something like this:


  static Crypto()
        {
            // Set up the Rsa provider to use the machine key store. If you don't,
            // creating the provider will fail when you run under ASP.NET. 


  CspParameters cp = new CspParameters();
            cp.Flags = CspProviderFlags.UseMachineKeyStore;


      // TODO: verify that we can encrypt 5 bytes, just so we don't get a 
           // false positive that makes us think we failed because of block size
     
I highly doubt that the developer who wrote it would have put up with this randomly indented presentation, so why do I have to? The problem is that developers love to hit the tab key to line things up, which generally inserts a tab character. Of course, different people and different editors choose different widths to use to display a tab character. Worse, it's easy to mix using tabs and spaces to align your code. After all, it'll look lined up to you, but when I open it, I get the mess above.


So, run, don't walk, to your favorite development tool and set the equivalent of this VS.NET option:



This will cause VS.NET to insert n spaces (instead of a tab character) whenever you hit the tab key, where n is whatever value you put in the “Tab size” textbox. I don't particularly care what number you use (although 2 is clearly the choice of the most discerning developers) - the point is that as long as you don't use tabs to line up your code, it'll line up for both of us.


This has been a public service message brought to you by the Terminally Picky Developers Association for Readable Code.

Wangdera.Controls 0.9.1 Released

Well, at least one person out there is using the Wangdera Control Suite...because they noticed I shipped a major bug with version 0.9. Basically, if you called the BatchFormat method to format a range of text, any text you subsequently typed into that range would be rendered as black on a black background. It's like, how much more black could this be? And the answer is none. None more black. Whoops.


I will protest that it's not entirely my fault. The problem is that the underlying Windows Rich Edit control (hate it!) will lie to you about what the format of the text is. So when I was saving the format of the text and then “restoring“ it later, it was causing a problem. But since I knew about the problem when I shipped 0.9, I probably should have caught the bug.


Anyway, it's fixed now, and you can download it. And it was a good excuse to refresh my memory on how branching and tagging works in CVS, since we're going to need it for FlexWiki.

Tuesday, December 7, 2004

Escaping ${} in NAnt Scripts

Today I was writing a NAnt script that calls an XSLT, passing in some regular expression replacement arguments so I could use replace occurrences of certain strings in an XML file. The problem I ran into is that the syntax for a regex replacement is ${group}, which is exactly the same as the syntax for a property in a NAnt script. I figured there must be an escape sequence in NAnt that lets you say, “No, I really want a dollar sign and a curly brace - I'm not specifying a property.“ But I tried backslash and the other usual suspects, then searched the web for a while. Nothing.


I banged my head against the problem for a while, and finally came up with this:


<property name="replacement" value="http://localhost/${product.name}-${websafe.version}${'${path}'}" />


It's the ${'${path}'} that actually does the trick: basically, I'm saying, “Use the string literal ${path}.“


I'm pretty sure this will only work in NAnt 0.85 and later, as that's when string literal expressions were introduced.

Why You Shouldn't Be Using Passwords of Any Kind on Your Windows Networks...

An interesting title for an interesting post. [ Robert Hensing's Incident Response WebLog ]

Sunday, December 5, 2004

Wangdera.Controls 0.9 Released

Babies do indeed take up a lot of time, but fortunately I'm still able to work on my little side projects now and then. So this weekend I was able to put the finishing touches on the 0.9 release of the Wangdera Control Suite. Specifically, I've fixed a bunch of bugs with RichTextBox2 and RichTextEditor, and added paragraph formatting capabilities in. So now you can do things like bulleted and numbered lists, set line spacing, and set the justification. Basically, I believe I've now exposed everything that's present in the underlying rich edit control. Combine that with the other performance and feature enhancements, and I think I've made something that's a real improvement over the (decidedly lame) RichTextBox.


Even though I labeled the version number 0.9, I really see this as more of a 1.0RC1 release. That is, I think it's ready for prime time, but I'm willing to believe there are still a few bugs. (Actually, I know there are a few minor bugs, but the ones I know about are because of weird behavior in the underlying control, so there's not much I can do about them.) Of course, I've already determined that the rich edit route is the wrong one for me, but like I said before, I still think it'll be useful for someone. So I got it done and posted so I can move on to the next thing. Enjoy!


If it seems like all I do on this blog lately is announce the release of software, well, that's because I've been working pretty hard on releasing software. :)


Now, on to understanding Uniscribe!

Wednesday, December 1, 2004

Nice Managed DirectX Site

I agree with David Weller on this one:



Big kudos to Andy "ZMan" Dunn who has created a website, The Z Buffer, that's completely dedicated to Managed DirectX goodness.  So, the best thing I can say is, "Stop reading this blog and get over there!" :-)

Monday, November 29, 2004

FlexWiki 1.8.1613.0 Now Available

FlexWiki 1.8.1613.0 has been released and is available for immediate download.


This release contains several major enhancements to FlexWiki, the most significant of which (IMO) is improved FireFox compatibility. Other important enhancements include the addition of a "Cancel" button to the edit page, a history list to show the most recently visited topics, improved support for non-ASCII characters, and WikiTalk enhancements.


Thanks to everyone that contributed to this release!

Sunday, November 28, 2004

NAnt 0.85 RC1

Looks like NAnt and NAntContrib have hit 0.85 RC1 status. I've been using an interim build of 0.85 for quite some time now in a production build script, and it's awesome. The support for functions in particular makes a lot of things a lot easier. I'd still like to see iteration over XML nodesets ala XSLT's for-each, but I'm not really complaining.


Check it out if you're still on 0.84.

Saturday, November 20, 2004

Setback in Text Editor Land

We took the baby with us up to Wharton this weekend so my wife could resume her MBA classes. That left me to look after the munchkin, and when she was asleep, alone in the hotel room with nothing pressing begging for my attention. Sweet! Uninterrupted hacking time!


I went back to working on RichTextEditor, which has been my obsession these last few months. My goal for the upcoming release is to add paragraph formatting, including the ability to add shading and borders. Since there are fields called things like wShading and wBorders in the underlying Rich Edit control that RichTextBox is a wrapper for, I thought I'd be able to do it without too much work. Foolish Craig.


The problem is that, although the structures listed in the Platform SDK support the full range of things that can be described in a Rich Text document, the Rich Edit control does not. It stores the values so that you can roundtrip the text with (say) Word, but it doesn't change the way that anything gets displayed. So you can, for example, tell the control to draw borders around a paragraph all you want, but it won't do a damn thing about it.


Now, that's not the real showstopper. I actually thought that might be the case, and came up with a few strategies for working around it. Specifically, what I tried to do was to let the Rich Edit control draw the text, and then draw borders and shading over the top of it with my own GDI+ calls. I even got a prototype working, drawing a shaded rectangle with a border in a fixed location over some text.


Unfortunately, the prototype displayed a problem that would eventually lead me to abandon my efforts: the stuff I was drawing flickered like mad. I spent an evening working through the problem with the ever-generous Ian Griffiths, but in the end we came to the conclusion that the only ways to do what I want involve horrendous hacks on top of nasty grungy bits on top of the hacks I'm already doing. Things like positioning a layered window over top of the RichTextBox window and drawing on that. Blech.


What it comes down to is that the Rich Edit control (and by extension RichTextBox and derivatives) is an 80% solution. Most of the time, you can get it to do what you want. But if you're an exacting bastard like me, and you just can't do without this feature or that, you're in the other 20% and you're screwed.


So, what am I going to do? First, I'll finish up RichTextEditor so that anyone who only needs stuff in the 80% can benefit from it. After all, it gets lots of good features from the underlying Rich Edit control, like sophisticated line breaking and support for East Asian languages. But once I get that out of the way, I'm going to write my own text editor control, from scratch, in managed code.


It's exactly the sort of “reinvent the wheel” scenario that I was hoping to avoid, but I don't think there's any way around it. And I'm looking forward to the experience, too, especially if I can pull it off the way I envision it. My only disappointment is that further development of FlexWikiPad is going to be delayed by however long it takes me to write a stable text editor control. Sigh.

Wednesday, November 10, 2004

Wangdera Controls Version 0.8

I just uploaded a new version of the Wangdera Control Suite, the most significant piece of which is RichTextBox2/RichTextEditor. In addition to fixing a bunch of bugs (some of them pretty significant), I've also added support for a new editing format: Link2. Link2 is a lot like Link, except you can set the underlining and the text color to whatever you like. The built-in Link format mandates blue text with a solid underline. That's a non-starter for an application like FlexWikiPad that needs to indicate whether the destination of the link already exists or not.


This turned out to be a major undertaking. Because of the inherent “it almost doesn't suck” nature of the underlying rich edit control, I found myself in a lengthy spiral of getting it almost working, only to discover that I need to change “just one more thing”. To give you some idea of how far down the spiral went, let me share that I had to completely rewrite the double-click handling of the control by intercepting and processing all WM_LBUTTONCLICK events. Quite a rabbit hole.


But I got it working, and I'm pretty pleased with it. My next steps for the control will be to add support for things like bullets, borders, and shading. The latter two are particularly important for what I want to do with FlexWikiPad. Once I get that done, I'll do a pass through to focus on whatever bugs I know about, then stamp it 1.0. After that, I'll integrate it into FlexWikiPad as part of my complete overhaul of the formatting engine. And if I do that right, I should be able to turn the knob way up on how powerful and customizable FlexWikiPad is. Wish me luck!

Tuesday, November 9, 2004

MusicPlasma

Things are returning to our new version of “normal” around the hacienda, and the munchkin is doing well. So hopefully I can blog a bit more now.


To that end, I wanted to point out this. Go there and type in your favorite band (Dream Theater for me). Cool, eh? Apparently, it's driven off of Amazon sales data via a web service. I've already found a few new bands that I think I need to investigate.

Monday, November 1, 2004

Election Prediction

I don't usually do political here, but I think this week of all weeks I can be excused.


Like another of my friends, I'll take a crack at predicting the election. Only I think it's going to be Bush. My reasoning for this is somewhat indirect. I'm basing it on the fact that I'm usually too optimistic. I'd really like Kerry to win, and I find myself thinking he could do it. But see, since I think he “could”, that means he's probably trailing in reality. Most polls seem to support that supposition, although margin of error and the electoral system mean that it's all up in the air.


I'd love, love, love to be wrong. I think Kerry will be an indifferent president, will make about the same decisions Bush would in Iraq (we're there to stay, basically), and won't be able to influence the economy that much (presidents get too much blame and too much credit there). Basically, I'm guessing we're looking at another Carter in Kerry. But I want the civil-liberty-supressing, short-sighted adventures we've got running the show right now out. And if nothing else, I want a Democrat to do the nominating of the next set of Supreme Court nominees.


Anyway, hope I'm wrong. To that end, at nearly 33 years of age I voted in this election. That make it my first vote ever (absentee because of the baby).

Thursday, October 28, 2004

A Dad Be I

If you haven't seen me for the last two days, it's for a very good reason...my daughter was born today after a long and difficult labor. “Woohoo!“ doesn't even start to describe it. :)


Details here.

Sunday, October 24, 2004

Book Review: Beginning .NET Game Programming in VB.NET

Let me get the full disclosure bit out of the way right up front: I was sent a free copy of this book by the publisher, I know two of the authors somewhat, and they mention this website in their references. That said, you can choose how large a grain of salt with which to take this review.


Frankly, I didn't think I was going to like Beginning .NET Game Programming in VB.NET. It's written in VB.NET (I'm a C# guy), it's a beginner's book, and most DirectX/gaming books suck. Fortunately, I was wrong.


I find that whenever I'm learning a technology, I generally want two books. I want to start with a good tutorial, and once I understand the basics, I want a good theory and reference book to help me explore in my own directions. Beginning .NET Game Programming in VB.NET makes absolutely no secret of the fact that it is very much the former, and not at all the latter. Frankly, had it tried to be a reference book, it probably would have failed, if for no other reason than that Tom Miller already wrote the best Managed DirectX reference/theory book.But David, Alexandre, and Ellen set out to write a tutorial work, and I think they did a pretty reasonable job.


The book starts off by writing a Tetris clone using only GDI+ (no DirectX), but builds up to a network multiplayer 3D game. Since the book is fairly short by computer text standards, it moves at a pretty good clip, presenting the material by writing and analyzing several different interesting games.


I'd have to say that this approach is the book's greatest strength: the fact that it is very much grounded in writing a game. That means it doesn't hand-wave over things like DirectPlay or DirectInput (although graphics does get the majority of the coverage). There's even some discussion of DirectDraw, which is fairly rare these days. And along with all the technology stuff, they constantly talk about the other factors for successful game development (e.g. “Source control is not optional” and “Write lots of small games first”). This is a goodness, as is the plethora of working game code.


The book isn't perfect, of course. I came across several errors, none too serious, that seemed to be largely related to the fact that much of the code in the book was ported from the C# companion work, which I haven't read. I also was a bit disappointed with the coverage of the issues around network play - I would have liked to have seen more discussion on this area. Still, it was arguably a good decision for them to cover less, not more.


Overall, I'd definitely recommend this book to anyone that had some VB.NET experience, and was interested in getting started with game programming.

Thursday, October 21, 2004

Longhorn Ship Date?


From the WinInfo Newsletter, (which is generally pretty good, IMO):



According to recent internal schedules I've seen, Longhorn and Office 12 are set to arrive concurrently on May 22, 2006. And the first Longhorn beta is set for February 16, 2005--the same beta 1 date I first reported in April. Naturally, this schedule could change--we're talking about Microsoft, after all--but the massive Microsoft infrastructure finally seems to be rumbling to life. For beta testers and Windows enthusiasts, 2005 looks to be a busy year.


Which I read as, “Don't worry about having to support Longhorn in the real world until at least 2008.” That's not an inidictment of the product. Just means that I'm going to go back to working on solving problems with technologies that my customers actually use - no sense getting too excited just yet.

Wednesday, October 20, 2004

Rewriting WSDL.EXE

The other day, I blogged about how easy it is to generate WSDL directly from a web service assembly, without having to set up an actual web service. Well, I decided to take it a step farther and see if I could generate the proxies directly, too. As it turns out, that's pretty easy, too.


The code turned out to be a bit long for a blog post, so I added it to my wiki instead. You can find the article here.


In addition to generating the proxy class without generating WSDL, I went ahead and added the code to walk over the generated code and strip out any type that isn't the proxy itself. Because we have several web services that share a set of types, and since we have defined these common types in a separate shared assembly to avoid type identity problems, this means the generated code looks just how we like it.


I haven't made the code bulletproof or terribly generic, since it's just for our use here at my client, but it should serve as a reasonable starting point for anyone that wants to produce custom proxies. One variation I can think of that would be useful would be to generate every type into its own file - that way if you had some types that you wanted to share and some that you didn't, it would be easy to automate which get tossed and which get kept.

Monday, October 18, 2004

Generating WSDL Without ASP.NET

Because wsdl.exe generates classes that don't look exactly like we want them to, I've set up a process at my client to generate custom proxies. Right now, we do this as a partly manual process - we've got a simple script that downloads the WSDL from a set of web services we've developed, then generates the default proxies by running wsdl.exe against them. Then we make some simple hand edits against them to make them look how we want them to.


There are two problems with this process:



  1. It requires hand editing the files every time we want to make a change.

  2. The turnaround sucks - we have to deploy the web service somewhere before we can get the WSDL.

The first one I'll fix later. It's pretty easy to do right now, since most of the changes are just removing code. At some point I'll cobble together some sort of sed script or something.


The second one is sort of a pain at the moment, though. We're using Continuous Integration, which is great because it means every time someone makes a change, we get a fully tested and installed version of the product running on a web farm about twenty minutes later. But because that's currently the only way we have of deploying (setup is somewhat complex), it means that if someone adds a [WebMethod], they have to wait 20 minutes for the deployment before they can download the wsdl and update the custom proxies.


I thought it would be pretty nice if instead there was some way to generate WSDL directly from the web service assemblies. Well, after poking around a bit with Reflector, and with a little help from Tim, I'd figured out the incredibly easy code to do exactly this. Assuming you have a web service class called MyService, the following code will spew the WSDL for it to the command line:


ServiceDescriptionReflector reflector = new ServiceDescriptionReflector();
reflector.Reflect(typeof(MyService), "http://localhost/vdir/Foo.asmx");



if (reflector.ServiceDescriptions.Count > 1){
  throw new Exception("Deal with multiple service descriptions later");
}


XmlTextWriter wtr = new XmlTextWriter(Console.Out);
wtr.Formatting = Formatting.Indented;
reflector.ServiceDescriptions[0].Write(wtr);
wtr.Close();


The URL that appears in the call to Reflect is not used except to populate the address element in the WSDL.


It'll be the work of minutes to roll this code up into a little EXE that takes the class name on the command line. I'll probably add an option to reflect over all classes in an assembly, looking for anything with a [WebMethod] attribute on it somewhere and emitting that, too.

Sunday, October 17, 2004

TDD Is Great...Except When It Isn't

I've been a big fan of Test Driven Development (TDD) ever since I first started using it to write FlexWikiPad (FWP) about a year ago. In fact, that was one of the reasons I wrote FWP in the first place, as an excuse to see what the fuss about TDD was. It turned out to be a huge win for FWP, and I've been using it for everything I write since then. Until now.


Having spent a good chunk of my free time in the last two months writing RichTextEditor, my first real WinForms control, I slammed headlong into a problem that many others have had before me: writing a test-driven component that has a complex relationship with its container. You see, the main tenet of TDD is based on the idea that you simulate the client of a component before you write the component. These simulations usually take the form of method calls, since usually what you're testing is a simple algorithmic class.


Sometimes what you're testing is a little more complicated, like a form. In cases like that, testing gets a bit more complicated too, because now you have to simulate a user clicking buttons and entering text. But even that isn't that bad if you separate out the windowy bits of the application (the view) from the bits that react to it (the controller). Then you just test the controller by making calls that simulate events in the view. That's how FlexWikiPad is developed, and I've been very happy with it.


But sometimes, what you're testing is a lot more complicated, like a WinForms control. There, the thing we have to simulate is the windowing system itself, since that's really the client of my control: Windows sends events to my control, and my control sends painting commands back. Making matters worse, at the time I didn't even know what messages to expect, and what should happen in response to them. As a result, I found myself at a loss to write tests for my control.


So I didn't. I tested it the old fashioned way: manually. Was it more error-prone? Yes. Does it make bug regression more difficult? Yes. Did I have any other choice given my time and resource constraints? Not really.


Note, however, what I am not saying here:



  1. That TDD doesn't work. It actually works very well when simulating the container isn't too hard. Which is most of the time.

  2. That TDD doesn't work in GUI scenarios. I've used it very succesfully when building applications. Just not RichTextEditor.

  3. That TDD never works for control development. The limiting factor is being able to simulate the exchange of messages between Windows and your control. If this is complex, at some point simulating it will be too much work. But if it's simple, you might manage it just fine.

  4. That you can't use TDD at all if you're writing a complex control. I actually still used it in RichTextEditor to develop the undo/redo logic of my control, since that stuff is decoupled from the rest of the control, and has a simple interface. It was very helpful for that portion of the development.

Another thing to be aware of is that I never really explored automating my testing process in other ways. For example. a macro recorder could be used to send keystrokes to my control, and possibly to test the results in one way or another. NUnitForms has a Recorder that might help in this regard.


Overall, I'm still a huge fan of TDD, and still plan to use it whenever I can. It's just that now I have a better idea of what “whenever I can” means.

Thursday, October 14, 2004

KDiff3 - a new favorite

Diff and merge tools are critically important to pretty much any real development effort. I've been using WinMerge for a few months, and have been mostly happy with it. It doesn't do three-way merge, but hey, it works.


Then the other day I ran across KDiff3 (which is free, same as WinMerge), and I like it a whole lot better. But some of the features it has that make me like it better than WinMerge:



  • Supports three-way merge

  • Supports directory merges

  • Seems to be faster than WinMerge

  • Will word wrap long lines at your option

But I think the nicest feature is that it shows you not just what lines differ, but actually what's different in those lines. That's really handy for long lines, or for those times where you're diffing an XML file that has no linebreaks in it.


On the downside, it's harder to use and uglier than WinMerge - it's clearly a developer power tool. Since I'm a developer, I don't mind.

Tuesday, October 12, 2004

RichTextEditor

Wangdera is my company (my wife's name is Wang - get it?), and I've set up a Source Forge project for us to publish whatever we feel like. Well, tonight I shipped the first release of the Wangdera Control suite. If you download Wangdera.Controls.dll, what you'll get is two Windows Forms controls:



  • RichTextBox2 - extends the Windows Forms RichTextBox control to allow you to do more types of formatting, as well as giving you a way to apply a whole bunch of formatting all at once in an efficient way.

  • RichTextEditor - extends RichTextBox2 with autocomplete lists and enhanced change notification.

I'm particularly excited about RichTextEditor, because autocomplete lists plus decent change notification plus advanced styling mean it's a pretty good basis for building simple (and perhaps not-so-simple) IDEs. I've already used it at work to write a lightweight SQL statement editor that turns keywords blue and strings green. I call it RichTextEditor not because I mean for it to edit Rich Text, but because I mean for it to be a text editor with rich display capabilities.


I wrote RichTextEditor with a particular goal in mind. You probably know that I've been working on FlexWikiPad for close to a year now. I've been using the scintilla control in it until now, via the ScintillaNET wrapper that makes it usable from .NET. For the most part, it's a pretty solid component, but I've always found the API to be a bit weird. And lately I've started to rub up against the edges of the styling model...nothing I couldn't work around, but it would make me do some stuff in a way I don't like.


Before running off to reinvent the wheel, though, I poked around a bit to see if I could find something else. The #develop IDE has an open source text editor component, but it's GPL, and that would make it hard for me to use in the places I want to use it. So I started looking at RichTextBox. It almost worked, and I figured if I could just tweak one or two things...two months later here I am, a shiny new invention I call “the wheel“ in my hand.


I could have just rolled RichTextEditor into the FlexWikiPad code, but I thought that this is the sort of thing that other people would want to use standalone. Hence the release in the Wangdera.Controls package. If you have a use for it, give it a try and let me know about any bugs or feature requests you might have.


My plan from here is to start integrating RichTextEditor into FlexWikiPad, while at the same time completely overhauling the formatting engine in FWP. I think I can increase performance, increase flexibility, and increase capabilities all in one go. Well see, of course; RichTextEditor works well enough in my tests but the true test is employing it in a real world application.


Here's a screenshot of the sample app I include with the Wangdera.Controls package. It shows some of the capabilities of RichTextEditor:


Tuesday, October 5, 2004

Disk Tray

I generally have no complaints with the computer I've been given to work on at my client. It's reliable, it's plenty fast, and they're good both about quickly fixing what goes wrong and not getting in my face with a bunch of arbitrary standards. However, the one complaint I have is that since I program with my headphones on, and since the computer actually sits under my desk and sort of behind me, I can't see or hear drive activity. Working on a laptop most of the time, I'm used to seeing the drive access light flicker as a sign that “something is going on”.


I knew I couldn't be the only person for whom this was a problem, and I was right. A few moments of Googling turned up Disk Tray, which seems (so far) to be a stable and capable little app for showing disk activity by blinking lights in the system tray.

Saturday, October 2, 2004

Pushing Towards a SolidRelease

David Ornstein is sending out a rallying call around FlexWiki.We're recruiting developers in an effort to fix the little things that are wrong with FlexWiki. It's pretty stable and fast now, but there are enough corner cases that an effort like this could really help. So check out David's post and sign up if you've got interest in contributing.

Wednesday, September 29, 2004

From EIF to log4net

You've seen my posts from time to time about Microsoft's Enterprise Instrumentation Framework (EIF). We were using it at one of my clients for quite some time to log all of our errors to various places. But recently we started experiencing massive slowdowns that I was unable to rectify, but that seemed to be attributable to EIF initialization. Some of our unit tests went from taking 5 seconds to taking 50 seconds.


I probably would have worked longer to fix it, but at the same time we were facing some serious configuration issues with EIF as well. Specifically, we were trying to instrument our code to record a pair of start/stop log messages for each method, which we could turn on or off at runtime based on our need for diagnostic information. While EIF certainly supports this, its configuration mechanism requires that we then list the name of every method in the EIF config file. While possible, that was impractical.


So I decided to see what it would take to switch to log4net. As it turned out, it only took one day. I'd isolated most of the logging code already, so I just had to change things in one place. And at the end of it, I was much happier. Not only does log4net appear to do pretty much the same things as EIF, it appears to be faster (although the jury is still out), it appears to be easier to extend, and it is definitely easier to configure. The last point is an important one for us - log4net has a hierarchical configuration scheme, meaning we can set defaults at the root and have them propagate to all our logging statements, rather than having to set them explicitly, as we do with EIF.


I'm not saying EIF is bad, mind you. It could be that I was doing things wrong. I know that Microsoft is overhauling it, so maybe their next version will be better. log4net does have a head start, being a port of log4j, which has been around for a long time. But for now, log4net meets our needs better...your mileage may vary.


There's a decent article on theserverside.net that goes more in depth, but here are what I found to be the major differences:



  • Ease of use. log4net felt easier to get started with. That might have been because I had already used EIF. The two are fairly similar.

  • Typed vs. untyped. log4net is “untyped“ in the sense that you log strings. In EIF, you log typed objects. This turns out largely to be a philosophical distinction except for:

  • Extensibility. Because log4net allows you to attach arbitrary name-value pairs to a logging thread (they call this MDCs), it's actually easier to extend. In EIF, the reliance on strongly-typed object hierarchies means I have to extend their schema. That turns out to be difficult for a variety of reasons.

  • Manageability. Like I said, the fact that log4net lets you inherit log settings down a hierarchy of loggers makes it easier to manage a large application. EIF, by contrast is “flat“, and forces you to manage every log source independently.

Other than that, I found the two pieces of software to be very, very similar. Which means I'd generally choose log4net in the future.

Tuesday, September 28, 2004

FlexWiki Available on SourceForge

Finally, finally, finally, FlexWiki has completed its long transition from its old home at GotDotNet to its new home at SourceForge. David Ornstein - the father of FlexWiki - has a post talking about it from his perspective. Here's mine.


Way back in February or March, I became disillusioned with the state of affairs at GotDotNet. I'd been working a lot on my tools FlexWikiPad and FwSync, and wrestling with the GDN tooling was becoming so annoying that it was starting to make me dread working on my stuff. So, I took matters into my own hands and moved my code to SourceForge, which I'd found much easier to work with. Not perfect, but better.


At the same time, I was still contributing to FlexWiki itself. Since that code was still on GDN, I started to agitate for a move to SourceForge. Why? Because I wanted it to be easier for me. :) But I also truly believed that it was a better place for FlexWiki to grow, and that the other developers would find the experience better, too. Of course, that was selfishly motivated as well, because more people working on it means more cool features.


David Ornstein was thinking along the same lines at the time, so we started to work together. Because I was complaining the loudest, I felt an obligation to help, particularly because I'd set up or help set up a few other projects on SourceForge before.


Thus began the long, long process of moving to SourceForge. For me, it was pretty easy, because my tasks were mostly technical: I'm the buildmaster for FlexWiki now, so I wrote a build script and set up a CruiseControl.NET Continous Integration server at http://builds.flexwiki.com. David's part was much harder; in addition to the technical tasks that he took on, he had to convince Microsoft (his employer) to allow this to happen. Since FlexWiki is only Microsoft's third open source project (after WiX and WTL), it was a very big deal, involving much coordination on David's part.


And it took months. This was highly frustrating for many people, but particularly so for would-be FlexWiki contributors. Several of them emailed me periodically saying, “When will the move be done?“ To which I could only respond: “Soon.“ Before long, it became obvious to me that I should switch that to the more truthful, “We don't know, but we're still working on it.“


But last night, at long last, all the legal documents had been signed, all the crucial technical details had been taken care of, the CNET article posted, and the word came down: the FlexWiki project site is now live. We've even got a release posted that has a few new features, like better support for Firefox. Plus, with continuous integration set up and (hopefully) working, I think we can more easily and frequently release contributions to the public.


Moving forward, we're definitely hoping that we can once again rally the FlexWiki development community, which has languished while David and I (mostly David) were working to get things transitioned. We'd particularly like to focus on bugfixes for a while - a fair number of defects have been logged but not addressed. There's still a fair amount of administrative work to do, too, like moving the bugs from the wiki where they live now to the SourceForge tracker where we'd like them to be. But we are finally blocked only by technical issues, which are the ones we know how to solve.


One of the questions I expect people will ask is, “How do I get involved?“ To start with, join either the users or developers mailing list, according to your inclinations. If you're of a developing mind, grab the source code and start poking around. Just be aware that we're going to be fairly careful with handing out write access - David talks about that more in his post.


Oh, and one exciting thing I almost forgot to mention: Ward Cunningham is a member of the FlexWiki project. Ward quite literally invented wikis, so we're really happy to have him involved.


This is the second major software release for me in as many weeks (the other being the MSDN Alpha), so it's a very exciting time for me. Unlike MSDN, though, I'm still very much a part of the FlexWiki effort. I'm sure we'll have a lot to do as people start to stretch the new system and we figure out how to run things, but I'm looking forward to it!

Wednesday, September 22, 2004

Looks Like It Works

It seems that the MSDN Product Feedback Site works: the System.Decimal bug that I complained about will be fixed in Whidbey Beta 2. Nice to see the loop closed.

Wednesday, September 15, 2004

MSDN Alpha Available

For the past two years, I've been working on a complete overhaul of the MSDN publishing system. Tim Ewald was one of the principal forces behind this effort, but there were plenty of other really smart people involved, too: I am not at all kidding to say that merely keeping up with them was difficult.


Well, quietly, last week, the first publicly accessible incarnation of what we've been doing went up at http://msdn2.microsoft.com/library/. We weren't supposed to spill the beans yet, but Jenfeng Zhang broke the news, and we've gotten the go-ahead to blog about it.


This is a complete rewrite of the MSDN publishing engine, from the ground up; we started with zero code. Of course, you'll notice that the look-and-feel of the docs remains largely the same: most of the changes lurk beneath the surface. For example, the entire publishing process is now deeply XML-oriented. Content comes in as XML, gets processed as XML, gets stored as XML, and even gets rendered as XHTML. This is going to allow MSDN to introduce a lot more services around their extremely rich set of documents...just wait and see.


Of course, some of the changes are visible, too. You've probably noticed that the URLs are vastly improved. For example, you can now surf to http://msdn2.microsoft.com/library/System.IO.Compression.GZipStream to get documentation about the new GZipStream class. We call this an alias. The “real” URL for this document is http://msdn2.microsoft.com/library/zs4f0x23.aspx, where “zs4f0x23” is what we call the short ID for the doc. We did a lot of work to make sure that this identifier is stable, so that URLs won't break.


Even though I've now finished my involvement with the project, I'm pretty excited about this release. It is the most significant (largest scale) piece of software I've ever shipped, and a lot of my code is running in it. Not that I was the primary developer, but there will be MSDN devs maintaining my code for quite some time to come. I learned a ton, not only from Tim, but from a woman named Kim Wolk without whom this software literally never would have shipped. She hates it when I mention her name, but I think she deserves more credit on this release than any other single person on the team, and it would be a crime if no one came out and pointed her out as the hero of this project.


So go give it a test drive and let MSDN know what you think. It's only an alpha, so don't be too surprised if something breaks or doesn't work the way you'd expect, but take my word for it: this is a huge step forward for MSDN, and by extension, for the developers that rely on it.

Sunday, September 12, 2004

FoamHenge

My wife and I had ourselves a little getaway this weekend, as she will be starting school again soon, followed shortly thereafter by the birth of our son/daughter/other. In other words, it was basically our last chance to do this (easily).


As we were driving around rural Virginia, we saw this:



I thought, "No, it couldn't be." But it was, indeed, a full-scale replica of Stonehenge, only made out of foam. Hilarious.




Monday, September 6, 2004

Viewing EIF Trace Service Logs

I've talked here before about problems I've had with EIF, the Microsoft Enterprise Instrumentation Framework. At the time, I thought that the bug I was seeing manifested itself as “I'm unable to open a remote logfile written by the EIF trace service.” Well, recently I had a chance to come back to this problem at my client, and after close to a week working on the problem, I finally found out that it has nothing to do with the remoteness of the files at all. Instead, it seems that because Windows 2003 and Windows XP use a different format to write the file, what's written on one system cannot be read on another. Since our webfarm runs 2003, and our desktops run XP, we were hitting the bug.


The real bummer is that there doesn't seem to be a way around this that doesn't involve rewriting the EIF trace service. It's really a problem with the fact that (according to Maros) the EIF trace service uses the Win32 OpenTrace/ProcessTrace APIs, and these are implemented differently on the two systems. D'oh!


The sort of good news is that other sinks still work fine. So you can write events to the Windows Event Log or to WMI right out of the box no problem...just not to the high-speed trace service that they provide. And they don't give you the source to the service, either, so I can't even fix the problem myself. Sigh.

Thursday, September 2, 2004

Complexity is in the Eye of the Beholder

I've got a few things in the pipeline, which is why it's been quiet around here. More on that later. In the meantime...


Ian has an interesting post here about complexity in APIs. Since he doesn't have a comment facility, I can feel justified in using it as an excuse to post here instead. :)


The part I found interesting was his analogy with cars, wherein he compares automatic and manual transmissions.



So the big problem is that in attempting to provide a simple abstraction, automatic transmission reduces the drivability of a car. I've found that the only way to get the best out of a car with automatic transmission is to learn what its behaviours are so you can anticipate the bad choices that it will make, and adapt your driving style to make it do the right thing. The irony is that this means you not only need to understand the underlying reality of the characteristics of the engine and gear ratios, you also need to understand how the abstraction placed on top of this works in order to be able to work around it.


Seen in this light, the manual transmission looks a whole lot simpler by comparison. It might have more levels, pedals and selectable options, but at least you know exactly what each control will do. There is no need to try and outsmart the abstraction simply to get it to do what you want.


The part that's interesting, of course, is that this is all completely subjective, and based on a rather large number of assumptions. Note, for example, “at least you know exactly what each control will do”. Living on Earth as I do, I've seen plenty of counterexamples to this on the roads every day. I'm sure we all know drivers who still can't operate a clutch properly, for all they've been driving one for years. And frankly, I think I'd rather the cell-phone-jabbering-morons of the world have that extra hand free. But for drivers like Ian, more precise control (probably) means more safety.


All of this is a way to say that the same interface can simultaneously be simpler and more complex, correct and incorrect, appropriate and inappropriate. It depends on the user. Which is why car companies give us a choice of manual or automatic, and why some software programs offer “expert” modes or other customizations.


It's not that I don't think Ian gets this - I'm sure he does - but after reading his piece I was left with the impression that manual transmission is superior, when in fact that just begs the definition of “superior”, which is inherently subjective.

Wednesday, August 25, 2004

Namespace &amp;quot;inheritance&amp;quot; and XmlSerializer

I've taken to writing much of my XML like this:


<foo:bar xmlns:foo="uri">
    <blah ... />
    <blah ... />
</foo:bar>


Which is to say, with an outermost element that's namespace qualified, but with all other elements belonging to no namespace. This is primarily laziness - I type a lot of XML by hand, and write a lot of XPath, and both are slightly easier with this sort of XML.


Where I got burned today was in trying to write a set of types that deserialize this XML. I started with this:


[XmlRoot("foo", Namespace="uri")]
public class Foo {
  private BlahCollection blahs = new BlahCollection(); 
 
  [XmlElement("blah")]
  public BlahCollection Blahs {
    get { return blahs; }
  }
}


And I expected it would work just fine. But I was surprised to find that when I did the deserialization, I got zero blahs in the resulting collection, even though there were two in the file. After banging my head against this problem for quite some time, I finally realized I needed to do something like this:


[XmlRoot("foo", Namespace="uri")]
public class Foo {
  private BlahCollection blahs = new BlahCollection(); 
 
  [XmlElement("blah", Namespace="")]
  public BlahCollection Blahs {
    get { return blahs; }
  }
}


Note that I'm explicitly setting the namespace to the empty string. Apparently, what was happening was that without this explicit command, the [XmlElement("blah")] attribute was assuming the Namespace value of the [XmlRoot] attribute above it. So at deserialization time, it was looking for an element called "blah" from the "uri" namespace, but finding one called "blah" that was from no namespace.


Although I know I'm nothing like the first person to come across this, it isn't called out in the docs in a way that was obvious to me, so I thought I'd mention it here.

Sunday, August 22, 2004

FlexWikiPad 0.93.1 Released - EnableVisualStyles Suspect

Ah, I have so much sympathy for Microsoft right now. I had just released version 0.93 of FlexWikiPad when I got email from several users complaining of some rather serious problems. Sure enough, I was able to verify them. D'oh!


Well, like any responsible software vendor, I committed to getting a patch out ASAP. And I did, just today: FlexWikiPad version 0.93.1 is available here. I think I got all the bad bugs that I know about. I certainly did a better job of testing this time.


There were about three different bugs that I had to address, but the worst one by far was a bit subtle. You see, users were experiencing actual crashes of the application when creating a new namespace. This was surprising to me because I had used this technique to catch unhandled exceptions. In my handler, I display a dialog box giving the user a chance to email me an exception report, and once they have, I let them go back to the application. In all the months I've been developing FlexWikiPad, this has always worked well enough to let me save my work whenever I hit some sort of unexpected problem. In other words, this was the first real “Oh *&%$ I lost work“ crash I'd seen.


The symptoms looked something like this: an unhandled exception would be thrown, after which the dialog would be displayed. The dialog would work fine (i.e. I could email myself an exception report), and then boom! The application would go down hard, with Application.Run() throwing an SEHException. This happens when someone in unmanaged code receives the dreaded COM HRESULT 0x80004005 (E_FAIL). This is a number I know well, but had hoped never to see again in my life.


I took a look at the code I've added to the application recently. On a whim, I tried removing from my Main the innocuous-looking line:


Application.EnableVisualStyles();


And sure enough, the problems went away. Which is to say, exceptions caused by bugs would still be thrown, but now they could be handled by my handler without an SEHException ensuing.


Needless to say, that line now looks like this:


// Application.EnableVisualStyles();


I can't say I understand why this change would fix the problem. EnableVisualStyles is the call you issue to ensure that you get support for Windows XP-style visual styles. Personally, I think they should have called it EnableUselessVisualFluff, but that's just me. A user requested it, so I wanted to try to support it. Of course, choosing between this and application stability was a pretty easy call.


What's really weird is that I just now compiled the source for version 0.93 to try to play around with this a bit, to see if I could maybe move the call around in Main to see what it would do. And now I can't get it to fail again. Sigh. Don't you just love software?


Either way, FlexWikiPad appears to be stable again. Download and enjoy.

Thursday, August 19, 2004

FlexWikiPad 0.93 Released

I've just released a new version of my major free-time black hole, FlexWikiPad. You can download version 0.93 here. New features in this, the latest version include:



So it's really coming along! My plans for the future look like this:


 Version 0.94 will probably be oriented toward a complete rewrite of the rendering engine, to make it totally customizable. That is, you'll be able to change a config file to add or alter: fonts, colors, and the regular expressions used to parse the document. I'll probably also take a look at performance, as I'm noticing some lag when typing in longer documents.


Version 0.95 will probably be about adding rudimentary online support, so separate usage of FwSync is not necessary. I'd also like to add a "Preview" function so you can see what your page will look like on the wiki to which you plan to post it.


Version 0.96 will probably be focused on adding hierarchical and historical navigation and fixing the tree view so it actually works.


And then if that's all the major features I can think of, I'll focus on fixing bugs, cleaning up the code, performance, and stability en route to a 1.0 release. If I can get all this done before the baby is born, so much the better.


Of course, for all I know, I'm the only one actually using the thing. But regardless, it's been an interesting experience writing a GUI app, which is not something I usually do. It's been particularly interesting developing it with a TDD approach, as GUIs present some unique challenges.

SHA-1 On the Ropes?

I'm not sure if you've seen this by now or not, but it's potentially devastating news for security pretty much everywhere if it turns out that SHA-1 has serious vulnerabilities.

Tuesday, August 17, 2004

I Need to Learn to RelaxNG

When Tim Ewald says XSD is too complicated, you know that at best the technology might be...a tad overengineered. So perhaps it's time to look into RelaxNG, an alternate schema language that lacks a lot of the weird complexities of XSD.

In truth, I've looked briefly at RelaxNG in the past. I found the basics to be very easy to understand...unlike XSD. But I haven't tried to use it in earnest yet, so my opinion is necessarily unformed. I think I'll make it a goal to use RelaxNG in some real context at the next opportunity where it's practical to do so.

Sunday, August 15, 2004

CruiseControl.NET Configuration

If you haven't checked out CruiseControl.NET yet, you really ought to. Continuous Integration (CI) is, in my opinion, only slightly behind Test Driven Development on the list of “most important software development techniques I've ever encountered,” and that puts it very high indeed. I've found CruiseControl.NET to be far more flexible and reliable than Draco.NET, the other major .NET CI tool.


Recently, I took on the role of buildmaster for FlexWiki. As we make the move to SourceForge, I thought it would be an opportune moment to get a CI system set up, primarily because it would help us avoid the “source code, source code, who's got the source code” hell that we've been in for months now. So as I sat down and set up a CruiseControl instance, I had a chance to think about our needs, and about how we should configure things to allow us to grow the project.


Well, after thinking about it for a while, I came up with something I rather like. Since it differs somewhat from the out-of-the-box CruiseControl experience, I've gone ahead and written up what I did here. Hopefully someone else will find it helpful.

Saturday, August 14, 2004

Conference Envy

There are two conferences I'd really like to go to this year: WinDev and the Applied XML Developer’s Conference 5. The confernces are both in late October, and both look to be awesome...just check the spearker list. I was invited to submit a talk to both of them, but had to refuse in both cases: my wife is pregnant, and her due date is right around then. Technically, she did say I could go, but she told me to buy a one-way ticket if I did. :)

Friday, August 13, 2004

End of an Era

It's been a long time since I've taught a DevelopMentor class: something like 18 months. Well, today I got an email from management that (rightfully, in my opinion) pointed out that it was time to make a decision about whether my name would continue to be associated with their brand. Totally fair: until now I was deriving value from them by appearing on their website, being on their internal mailing lists, and so forth, without delivering any value back to them.

I stopped teaching back in March of 2003 because I was dead tired of it. Some guys can go on teaching the same material month in and month out. I guess they derive their satisfaction from seeing people “get it” for the first time. I think that sort of attitude is fantastic, and that devotion to the educational experience paired with technical excellence in the instructors is what drew me to DM in the first place. My problem was that I simply couldn't face presenting the same 400 slides one more time. I think I'd taught slight variations of their .NET curriculum 25 or 30 times by then. It was hard to get up and be energetic and enthusiastic at that point.

So I sort of slipped sideways into consulting. I got lucky and had a bunch of gigs come my way, and they paid well, and for a while I could simply and honestly say I was too busy when DM would call and ask me to teach a class. But as time passed, I realized that I was learning a lot consulting, and that the idea of having to teach a class was something that I didn't look forward to at all. So somewhere in the last 18 months, I left DM mentally.

Today I left it for real. I let them know that - while I consider having taught at DM equivalent in prestige and educational value to my Masters from MIT - I would not be continuing my business relationship with them.

In practical terms, this doesn't mean much beyond that my name comes off their website, candera@develop.com stops working, and I don't get to be on their internal mailing lists any more. And coming as it does after such a long break, it's hardly traumatic. Or even surprising. Still, I can't help but feel a certain sense of...not loss...maybe “transition“ is the right word.

I don't know if I'll teach again in the future or not. I feel like I'm not done learning how to be a “real” developer yet, but I also know that my attention span is short enough that I'll have to do something different at some point. And I could see speaking in some form - classes, conferences, user groups, whatever - being a part of that.

Tuesday, August 10, 2004

Old Site RSS Redirect Added

If you just got a big pile of CraigBlog posts today and are wondering what happened, it's because I finally fixed the redirects for the RSS feed on my old blog. It came to my attention that not only I had forgotten to do so, but that at least a few people were still subscribed to the old, dead feed. Since I'd hate to deprive anyone of my brilliant insights (hah!), the situation has now been remedied.


If you were pointed to the old feed, though, you should really edit your subscriptions to point directly to the new feed.

Saturday, August 7, 2004

Managed Space

Jason Whittington has a blog. Jason's a friend from my DM days; these days he owns the DevelopMentor .NET curriculum. Looks like he's playing with Whidbey these days! Subscribed.

Too Much Fun With Anagrams

Inspired by David Ornstein (Sodden Rat In IV), I've been having some real fun with this site the last few days. It's nothing new: I go there every few years. But I found some good ones this time:


Craig Andera = In A Drag Race = Grand AI Race


I don't have the best name for anagrams, though, so I also tried “Mister Craig Alan Andera” and got “Giant Crania Mars Leader”, “Stir Male Arcadian Anger“, and “Tim's Anger: Canada Rail“.


Of course, my personal favorite from that same set has to be “Incites Real Rad Anagram”. :) So, since it is apparently my destiny to get others to waste time this way, I'm asking you (yes, you) to post your own best picks of your name/name variation. Don't have a blog? Post a comment here! Let see how many good ones we can get!


 

Wednesday, August 4, 2004

Coalesce

Recently, I posted some complaints about XmlSerializer and about Windows Explorer. First of all, thanks to those who posted comments trying to help out - they led to a better understanding, and to a solution, respectively. They also led to me finding out about an interesting tool. Since I know not everyone reads the comments of every post, I thought I'd coalesce the interesting bits here.



  • It turns out the XmlSerializer behavior is expected, and documented. Mostly, it's fallout from the XSD “fixed“ capability, which is basically pure evil: why would you make me go look at a schema to determine what the value of something should be? Yuck.

  • Several people correctly pointed out that files were taking forever to delete because my Recycle Bin had too much crap in it - I had thought I had emptied it recently, but I guess not. Ian Griffiths, however, posts that he uses waste.exe from Tim Tabor's BinManager to automate the process of cleaning out his Recycle Bin. Sounds interesting - I'll definitely have to check it out.

  • While I was poking around trying to figure out my XmlSerializer problems, I came across this little nugget about how to get XmlSerializer to show you the code it generates...now that might come in handy.

  • On top of that, the very cool mvp-xml project just released SGen, which lets you do some pretty serious customization of the XmlSerializer process.

Beatallica

This is too good not to share. Best title? I think it has to be “The Thing That Should Not Let It Be”.

Sunday, August 1, 2004

Please Tell Me Why

Please tell me why, when I delete a file in Windows Explorer (select file, hit the delete key), it takes like 30 seconds. From the command line, it takes no time at all.

Wednesday, July 28, 2004

Wiki and Wiki; What is Wiki?!?

I've had a number of people talk to me lately about wikis, and from these conversations it has become clear to me that at least a few are unclear on what they are about. So, I'll take a stab at defining them.


First and foremost, wikis are about authoring a set of static HTML pages. That's it. If you're trying to do something with a wiki that would be hard to do well with a set of free form HTML pages written using Front Page, then you probably won't do it well with a wiki. A great example of this is discussions: wikis pretty much suck at threaded, back-and-forth conversations, because free form, static web pages pretty much suck at this. Note that more constrained or more dynamic web applications might still do a decent job (think message boards), but a big ol' pile o' HTML is a long way from being a discussion board. 


Still, for all the things it isn't good at, there are lots and lots of useful things you can do with a set of hyperlinked HTML pages. So why wiki? Well, a wiki gives you two things:



  1. Collaboration.

  2. A simple authoring language.

The collaboration one is the one you generally hear about most. The idea that lots of people can walk up to your website and author their very own page, or even edit one that you wrote is totally crazy-sounding, but turns out to be immensely powerful.in a lot of situations. Of course, because we can't trust everyone not to deface the shared page, most (not all) wiki engines offer version control to make it easy to undo what others have done, but I don't think version control is really central to the Zen of wiki.


However, I happen to think that the other major facet of wikis is every bit as important as the first: the fact that they introduce a simple authoring language. For example, if you look at the language that FlexWiki offers, it's simple do make something bold - you just *surround it with asterisks*. The wiki engine then interprets this into HTML that makes the enclosed text bold when the page is viewed. While this isn't much simpler than surrounding the same text with the equivalent <b> tags, it turns out that this syntax (and the other syntactic elements a good wiki language offers) are just _enough_ simpler to lower the bar on contributions to the point where people are actually willing to spew their brains onto a page. 


It really says a lot about human laziness that harnessing its power can do so much. :)

Tuesday, July 27, 2004

DefaultValue and XmlSerializer Don't Mix?

Maybe someone can explain to me why this:


using System;
using System.Xml.Serialization;


public class Foo {
  [XmlAttribute]
  [System.ComponentModel.DefaultValueAttribute("three")]
  public string value = "three";
}


public class App {
  public static void Main() {
    XmlSerializer ser = new XmlSerializer(typeof(Foo));
    Foo foo = new Foo();
    ser.Serialize(Console.Out, foo);
  }
}


produces this:


  <Foo />


whereas if you remove the DefaultValue attribute, you get this:


  <Foo value=”three” />


which is what I would expect. This is particularly troubling, since wsdl.exe will generate proxies that use System.ComponentModel.DefaultValueAttribute when it sees schema types with fixed value constraints.


I have to assume this is a bug in System.Xml.Serialization, but I'm willing to believe that there's some subtlety I've missed. I've confirmed this behavior in CLR 1.1 and 2.0.40607.

Sunday, July 25, 2004

I Won't Miss It

Via Tim Bray, this amusing little story about how IE is not quite as universal as it once was. I for one, wouldn't miss it for a second if it went away tomorrow: I use Firefox, which is far superior.


Actually, I would miss it a little, but only because there are a few important sites that are busted in anything but IE. Sadly, all FlexWiki sites fall into this category (but hopefully not for much longer).

Saturday, July 24, 2004

Mixing Forms and Windows Authentication

A client of mine wants to provide single sign-on (SSO) capabilities in their web application, so that users don't have to type in their domain password when authenticating to the application. The twist? Only some users of the application use SSO: the rest have accounts that exist only in the application database. So we couldn't just flip on “integrated authentication” in IIS and party on. But with the help of Keith Brown, I was able to figure out a pretty nifty solution.


The trick was realizing that if you enable both “anonymous“ and “integrated“ authentication for a particular virtual directory, the browser won't try to authenticate to the web server until it receives a 401 (Unauthorized) back from the web server. But you can issue your own 401 any time you like! So what I did was to just set up Forms authentication as normal, but also provided a checkbox on the login form that said, “Use my network credentials.” Then, in my login form, I did something like this:


public class Login : Page {
  protected
Label ErrorMessageLabel;
  protected
TextBox UsernameTextBox;
  protected
TextBox PasswordTextBox;
  protected
CheckBox CheckBox1;

  public void Page_Load(object
o, EventArgs e) {
    if
(IsPostBack) {
      string authenticatedUser = null
;
      if (CheckBox1.Checked)
// Use their network credentials
     
{
        string
user = Request.ServerVariables["LOGON_USER"];
        if (user.Length == 0)
// They haven't provided credentials yet
       
{
         
Response.StatusCode = 401;
          Response.StatusDescription = "Unauthorized";
          Response.End();
        }
        else
// They have
       
{
         
authenticatedUser = user;
       
}
      }
      else
// Use the username and password they provide
     
{
         if
(IsPasswordOK(UsernameTextBox.Text, PasswordTextBox.Text)) {
          authenticatedUser = UsernameTextBox.Text;
        }
      }
      if (authenticatedUser != null)
// They authenticated successfully
     
{
        // Issue the Forms Auth cookie and send them on their way

        FormsAuthentication.RedirectFromLoginPage(authenticatedUser, false
);
      }
      else
// They didn't
     
{
       
ErrorMessageLabel.Text = "Invalid username or bad password. Please try again.";
     
}
    }
  }
}


What this does is - when the user submits the login - check to see whether they want to authenticate by providing a username and password (normal Forms authentication) or whether they want to authenticate automatically, using their logged-in credentials. Right now, I'm figuring this out by having them explicity check a checkbox, but I do lots of other things. For example, I could have them always enter their username, and then go look in the database to see whether they're supposed to get a SSO login or a normal one. Or I could have them check the checkbox once and remember their settings forever after in a cookie.


Whatever mechanism I decide on, the trick here is that I can force the browser to authenticate by sending back a 401. Then, in subsequent visits, I can check the LOGON_USER server variable to see if the authentication was successful or not. If it is, I'm perfectly welcome to issue them a valid Forms Authentication login, secure in the knowledge that the user has proven knowledge of their password to IIS already.


If the user is using IE, the authentication will happen automatically, using whatever credentials they're logged in to the client machine with. It works in Firefox, too, but they get that little username/password popup dialog box. Oh well - maybe the Firefox people will add auto login in a future release, or someone will write an extension. But failing that, providing SSO only to IE users is good enough for us.

Friday, July 23, 2004

Keith Brown Seeks Help - See Your Name Up In Lights

Keith was helping me out with an interesting security problem yesterday (more about that in another post), and he pointed me to his online book as a resource for some code I needed. I'd read almost all of it already, and we fell to talking about how it would be to port it to a wiki format. After all, it's a series of interconnected pages that occasionally need to get updated, which is pretty much the definition of what a wiki is good at.


Well, I wake up this morning and discover that he's already started moving the darn thing over. And he's looking for your help to finish porting it. I've already signed up to help - you should, too: being part of distributing good information about security is a community service.

Wednesday, July 21, 2004

MIT Grad Wins Miss Massachusetts

While others may have different preconceptions about women at MIT, I've always known there are some great-looking women there...after all, I married one. Now, an MIT grad has won Miss Massachusetts and will compete in the Miss America pageant. The coverage here is a bit condescending, but her take is interesting nonetheless.

Tuesday, July 20, 2004

Announcing the Pluralsight Wiki

Being as involved as I am in FlexWiki, it seemed odd to me that I have a repository of articles (i.e. CraigWriter) that I edit once in a while that isn't in wiki form. After all, I've spent a large chunk of my free time in the last six months writing tools to make editing FlexWiki easier. So this weekend, while I was in Minnesota attending a wedding of a close friend, I found myself sitting around my parents' house with no broadband Internet. After recovering from email withdrawal, I decided it was a good time to port my content to the heretofore empty Pluralsight wiki.


And so I have! This change of technologies brings several benefits:



  1. It's easier for me to edit things in real time.

  2. I can ditch the hand-rolled code I wrote to support my articles.

  3. Other people can contribute more easily.

  4. The wiki has a series of RSS feeds so people can find out about changes and new articles.

  5. Since FlexWiki is open source, we get the benefit of any improvements the community makes, without having to wait for Craig to get free time.

I think I've got everything moved over except the translations of my Direct3D tutorial. Because they're not in English, it's a bit harder for me to make sure I got everything right, and I'm punting it for now. I do plan to move those as well, though, after I recover from being offline for four days. I'll also put up redirects for the existing repository before too long.


In the meantime, have a look at the new wiki and let me know if you see anything wrong, stupid, or broken.

Monday, July 12, 2004

NUnitAsp First Impressions: I Like It

I've been playing around with NUnitAsp for about 15 minutes now, and I already like it a lot. It gives the ability to make requests to an ASP.NET web page, and then easily verify that the contents of various server controls have rendered correctly. And it plugs into NUnit, so you get that same red/yellow/green display. I even managed to make it populate a login form with my credentials, click the submit button, and verify that it redirected me to the right page. Took about three minutes to write.


In addition to being useful for doing TDD of web apps, this is definitely something that should make writing build verification tests easier. Build verification tests (BVTs) are distinctly different from unit tests, in that they are intended to work against the system as a whole, rather than against a small piece of code. So as one of its last steps, the build script can copy the newly compiled web content to the file system, create a virtual directory, then use nunit-console to run tests that hit various pages, making sure everything works okay as deployed.

Sunday, July 11, 2004

Taking a Small Step to the Left

My blog has moved again! Only, not very far this time: instead of http://pluralsight.com/craig/ it now lives at http://pluralsight.com/blogs/craig/. The Pluralsight guys had to restructure the site a little to make things run more smoothly, and we figured better sooner than later. Everything should already be getting redirected automatically (including the RSS feed), but you can update your bookmarks and aggregators if you like. Please let me know if you find any broken links or missing content.


Also, apologies if your aggregator spewed a bunch of my old posts as new ones, but at least now you know why.

Thursday, July 8, 2004

XmlInclude - Not Quite as Useless as I Thought

Simon Horrell pointed something out to a bunch of us the other day that I thought was quite interesting. It has to do with the [XmlInclude()] attribute that's part of the System.Xml.Serialization stuff. Ordinarily, you use it on a base type to indicate that when serializing instances of that type, they might really be instances of one or more subtypes. This allows the serialization engine to emit a schema that reflects the possibility of really getting a Derived when the type signature is Base. For example, consider the following web service:

<%@ WebService class="Service" Language="C#" %>

public class Animal {
  public int legs;
}

public class Mammal : Animal {
  public int nipples;
}

public class Service {
  [WebMethod]
  public Animal GetAnimal() {
    return new Mammal();
  }
}

Note that GetAnimal is typed to return an Animal, but actually returns a Mammal. Well, if you were to look at the XML that came back from this method, you might be surprised to see that it looks like this:

<Animal>
  <legs>8</legs>
</Animal>

You'll observe that this result does not contain any mention of nipples - the “Mammalness” has been lost. Which makes sense - from an XML standpoint, you told me that the operation returns a type that just has legs.

One way we can “fix” this to give a result more in keeping with our OO expectations is to use the XmlInclude attribute on the base type, to list all the types that we might wind up substituting. It looks like this:

[System.Xml.Serialization.XmlInclude(typeof(Mammal))]
public class Animal {
  public int legs;
}

And if we run our web service now, we get this XML back:

<Animal xsi:type="Mammal">
  <legs>2</legs>
  <nipples>3</nipples>
</Animal>

Note the presence of the xsi:type attribute, which says, “This thing is actually a Mammal.” If you're generating a .NET proxy using VS.NET's Add Web Reference or the wsdl.exe command line tool, you'll even find that when you check the type of the object that comes back from the web service call, it's a Mammal, which derives from Animal. This is possible because in the schema for the web service, there's a bit that says that a Mammal is an extension (an XML schema term) of Animal.

If you're an OO person, however, you probably don't like the fact that you have to hang that XmlInclude attribute off the base type. The idea that a base type has to know about its derived types in advance is, well, just plain weird. This is where Simon comes in. He pointed out that you can actually put the XmlInclude attribute on the method instead of the base type. So if we change our web service to look like this instead:

<%@ WebService class="Service" Language="C#" %>

public class Animal {
  public int legs;
}

public class Mammal : Animal {
  public int nipples;
}

public class Service {
  [System.Web.Services.WebMethod]
  [System.Xml.Serialization.XmlInclude(typeof(Mammal))]
  public Animal GetAnimal() {
    return new Mammal();
  }
}

We'll get the same result (i.e. it'll have legs and nipples and use the xsi:type attribute) as putting the attribute on the Animal type. But putting it on the method is much more attractive from a code point of view, since it doesn't bake assumptions about type derivation into the base type. Rather, you put them on the method, where you probably have a good idea about what exact types are being returned.

Now, that said, I wouldn't write web services using this. Why not? Because if you care about interoperability, writing schemas that make use of extension elements and xsi:type isn't exactly “polite“. You don't know what technology your clients will be written in, and not all languages even have type derivation. Those that do, don't necessarily take the same view of it as C#. And even if they do, not all toolkits are smart enough yet to both map the XSD extension correctly and to look for the xsi:type attri