apocryph.org Notes to my future self

30Aug/070

Random Apocalyptic SF Review

Yesterday I read Cory Doctorow’s apocalyptic novella, When Sysadmins Ruled the Earth, which was hyped quite a bit on Boing Boing etc but I had no interest in reading until I saw it was included in an anthology of apocalyptic SF. As you may know, I love apocalyptic fiction of all kinds. This post notes some of the works I’ve enjoyed.

The best overall TEOTWAWKI book I’ve read has to be A Canticle for Leibowitz by Walter Miller Jr. It’s got all the great elements of the apocalypse, with a few unique elements that make it great. I won’t spoil it, but the outline is, the world ended in thermonuclear war, many of the survivors blamed technology and went on a book-burning freakout trip, and as a result, the human race centuries hence has only an archaeologist’s understanding what what life was like Before. The Catholic Church has survived, and resumed its Dark Ages role as guardian of literacy and knowledge, though with some striking differences to today’s Church. Outstanding book, though the sequel bored me to tears and isn’t worth the trouble.

Of course, no list of TEOTWAWKI fiction is completed without a mention of Cormac McCarthy’s The Road, which I’m sad to say is an Oprah’s Book Club book, though I urge you not to judge it too harshly. What really struck me about this book is the incredibly sparse nature of the prose, which fits in perfectly with the desolate world in which the story is set. As a philistine, I don’t get alot of exposure to that sort of multi-dimensional literary expression, and it kind of scares me, but in a good way.

So where does Sysadmins fall? Actually, I thought it left alot to be desired. The reason I enjoy the post-ap genre is that it provides a literary experience that I can more easily immerse myself in. For whatever reason, when I read stories that feature all manner of emotional plot devices, I experience them as a spectator (which I often enjoy, to be sure). It’s only post-op fiction that I can get into myself, such that I experience the story more immediately, as though I’m there and witnessing the end of the world myself. I don’t think this is so much due to the masterful literary genius of post-ap fiction writers, as it is due to an odd quirk in my personality, but nonetheless it makes it easy for me to enjoy this genre.

That said, Sysadmins fails what for me is a basic post-op test: plausibility. When one is writing about the end of the world, there’s a requisite suspension of disbelief involved already, and there’s not much left over for far-out TEOTW scenarios. Nuclear holocaust is safe, as is pandemic. I’ll even accept world-killing asteroid or alien invasion. However, in Sysadmins, Doctorow wants me to accept a spontaneous, uncoordinated day of bad behavior on the part of every terrorist organization and nutjob in the world, catalyzed by we-dont-know-what. You’ve got your EMP, your bioweapon, your nukes, your conventional bombs, your dirty bombs, etc. As someone who will happily accept an alien invasion plot, I must say the Sysadmins plot defies belief.

Apart from that, Doctorow nails all the geek archetypes perfectly, and for that reason alone Sysadmins was amusing and worth my time. However, it’s not going into the annals of post-ap kickassery.

29Aug/070

Updated apocryph Drupal theme

I’ve made some minor adjustments to the apocryph.org Drupal theme. The original apocryph theme was based on a ripoff of the built-in Drupal 4.x theme, and was showing its age. It wasn’t compatible with some nice Drupal 5.x features like autocompleting tag names, and auto-collapsing form field groups. Mostly the enhancements are to the posting side of things and thus benefit me exclusively, but while I had the hood up I tweaked a few colors to make the site look a bit less like a Spartan military barracks.

26Aug/073

Rendering disabled ('grayed out') image buttons in WPF

Earlier today I was ranting about lack of built-in support for grayed-out image buttons in WPF. I’ve come up with two workarounds; one correct, and one workable.

The first one I figured out by looking at some C# code here. The idea is to use a FormatConvertedBitmap to convert the original image to grayscale. This works, but then kills the alpha channel so your transparent PNGs aren’t transparent anymore. Thus, I also use the OpaqueMask property of Image set to an ImageBrush based on the original image. It’s nasty, complicated, and (probably, in a real app) slow. Here’s the markup:

<TextBlock>
    This is a grayed Image loaded from a BitmapImage, with an opacity mask :
    <Button IsEnabled="false">
    <Image Height="16">
        <Image.Source>
            <FormatConvertedBitmap DestinationFormat="Gray32Float">
                <FormatConvertedBitmap.Source>
                    <BitmapImage UriSource="Images\OutdentHS.png" />
                </FormatConvertedBitmap.Source>
            </FormatConvertedBitmap>
        </Image.Source>
        <Image.OpacityMask>
            <ImageBrush>
                <ImageBrush.ImageSource>
                    <BitmapImage UriSource="Images\OutdentHS.png" />
                </ImageBrush.ImageSource>
            </ImageBrush>
        </Image.OpacityMask>
    </Image>
    </Button>
</TextBlock>

As you can see, the original image is read into FormatConvertedBitmap, which is used to convert to Gray32Float (Gray8 is probably better), and used as the Source of an Image. The Image‘s OpaqueMask is set to the original image via an ImageBrush. As you test this out, don’t use Expression Blend; the designer view renders the grayscale Image elements as blank, even though in IE or a desktop XAML app it looks fine.

I also have NFI how this solution could be generalized into a style so you don’t have to repeat this for every button. Obviously the original image and grayscale version could be expressed as resources (I did it my way for clarity), but it’s a long way from there to a trigger based on IsEnabled that replaces an image with a grayscale version of itself.

That leads me to the other solution, which blows but is workable. I found that here. The idea is that you don’t grayscale the image at all; you lower its opacity so it looks more faded, and in the case of a gray control background, grayed out. This happens to be easily expressed as a style, like so:

<Window.Resources>
    <!-- El Cheapo hack to make images within disabled toolbar buttons appear 'grayed out'.  This doesn't
    gray them at all, but lowers their opacity so the (usually gray) background of the button shows through.
    If WPF had a built-in facility for grayscaling images in disabled buttons, this kind of icky kludgery wouldn't
    be necessary -->
    <Style TargetType="{x:Type Image}" x:Key="toolbarImageStyle">
        <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}, AncestorLevel=1}, Path=IsEnabled}" Value="False">
                <Setter Property="Opacity" Value="0.50"></Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

Any Images contained within a button and with Style set to toolbarImageStyle will have their opacity adjusted to 50% when the button is disabled. The original post called for an opacity of 25%, but that was too faded in my opinion. Adjust the value to taste, but don’t expect to exactly duplicate the true grayscale effect; colors are still visible in the buttons, they just look a bit faded.

So, there you have it. I’m going with the latter solution since it’s easily workable and almost right, but I’m still fuming over WPF’s inability to handle a feature that MFC has had for the duration of my programming career. Pretty soon I’ll be like those old mainframe curmudgeons who bitch about C++ and insist C and 64K of RAM is all anyone ever needed. Then I’ll know it’s time to quit the software industry and go into yoga instruction full time.

26Aug/077

What the HELL is wrong with WPF?

This weekend I’ve been working on one of my many self-edification projects, and against my better judgment I was implementing it with .NET 3.0/Windows Presentation Foundation, mainly because of the markup-like UI model which fit nicely with a few of my project’s idioms.

Anyway, I wanted to get a quick hit this weekend to keep momentum going, so I thought I’d put together the rich text interface of the project first. This should be stupid-easy, since WPF contains a RichTextBox class that does everything you could ask for with rich text, and the underlying content model is itself a XAML document, a FlowDocument. Too easy.

Unfortunately, RichTextBox doesn’t ship with the standard rich text toolbar, for doing things like bold, italics, etc. No problem; WPF has a toolbar element too. I wired up a bunch of buttons, each using the standard icon for its corresponding function, and set the buttons to invoke WPF commands like EditingCommands.ToggleBold, which the rich text box knows how to handle. “Wow”, I thought to myself, “this WPF thing isn’t half bad!”.

Then I noticed something. When commands are disabled (for example, the ‘Cut’ command is disabled when there’s nothing to cut), the toolbar button doesn’t respond to mouseovers or clicks just like a disabled button wouldn’t, but the icon on the button isn’t grayed out like one would expect. Then I tried something simpler; I created a Button with an Image in it, and explicitly set the Button‘s IsEnabled property to false. Sure enough, the image was still not grayed out.

Then I used Microsoft Expression Blend (a tool about which I could write a whole stream of angry rants) to show me the built-in XAML template for the Button control. Imagine my surprise when I discovered the only logic in the template that deals with rendering the disabled button is setting the foreground color to gray. That’s _it_. No wonder, then, that my images weren’t rendering differently; the foreground color has no effect on images.

You can see for yourself. Type this XAML code into XamlPad and see what happens:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel HorizontalAlignment="Left">
        <Button>
            <TextBlock>This button is enabled
                <Image Source="http://apocryph.org/themes/apocryph/logo.png" Width="32" />
            </TextBlock>
        </Button>
        <Button IsEnabled="false">
            <TextBlock>This button is disabled
                <Image Source="http://apocryph.org/themes/apocryph/logo.png" Width="32" />
            </TextBlock>
        </Button>
    </StackPanel>
</Page>

You’ll see two buttons, one with grayed-out text, but both with the same fucking image.

So let’s ponder this a moment. Back in 1995, I got my first copy of Visual C++ for free from a guy named Mike Strock (this was back when companies sold compilers for an outrageous sum, and thus I couldn’t afford them). One of the kickass features that blew me away was the MFC document/view model, where toolbar buttons mapped to commands, and would automatically disable themselves if the commands were disabled. Somehow, MFC automatically grayed out the toolbar button icons as well. It was incredible. “Surely”, I thought, “programming can’t get any easier than this”.

Apparently, I was right, coz here we are, 12 long years later, and we’ve taken a huge fucking step backwards. Now, don’t get me wrong. Using WPF I can easily make a button which contains a spinning 3D cube playing videos on each face that turns green when the mouse goes over it, all without any C# code. Unfortunately, no one would ever want to do that, while it’s easy to imagine a situation wherein you’d want toolbar icons to gray themselves (like, I dunno, every Windows application ever made).

This gives me a great startup idea. I’ll found a company in some tort-free jurisdiction like Costa Rica, called “FuckIt, Inc”. We’d offer an exclusive “Fuck This Shit(tm)” package, wherein programmers who can no longer bear the absurdity and kludge which is modern software engineering would be cryogenically frozen in a bunker on a secret island off the coast, to be revived 100 years hence or when the software industry gets its head out of its ass, whichever comes first. One of the test cases used to determine if the industry has its head out of its ass yet would be this one:

Using the latest development tools from the vendor of the most popular desktop operating system on the planet, is it easier to create toolbar buttons with icons that automatically disable themselves when the action they correspond to is disable, or to create a huge button containing a spinning 3D cube with video playing on each face? If the answer is the latter, as it is today, then the programmers stay frozen.

UPDATE: I’ve got a couple of solutions, here. Neither of them are optimal, but then, neither is life itself.

25Aug/070

Underpublicized Visual Studio 2005 Feature: Image Library

I found myself needing some standard toolbar icons today, for things like copy, paste, increase indent, etc. Purely by luck I stumbled across the Visual Studio 2005 Image Library, which seems to be one of the best kept secrets of VS2k5. Before you take a Word screen-grab and steal Microsoft’s icons, check the image library first; what you need is probably there already.

23Aug/070

Another PowerShell Dick Move: Error messages that don't mean what they seem to mean

Here’s another shitty PowerShell gotcha:

The error message ‘No Windows PowerShell Snap-ins are available for version 1′ doesn’t mean what you think it means.

I had this problem running a 32-bit C# app trying to load the (apparently 64-bit) Exchange Management snap-in. The yaks just keep coming.

23Aug/070

PowerShell Pet Peeve Number 1: Grammar

Hot on the heels of my first PowerShell gotcha comes my first PowerShell pet peeve: grammar.

Apparently, PowerShell was developed by someone who either a) doesn’t speak English very well or b) doesn’t give a shit about English grammar. What am I talking about?

Well, let’s say I want to order you to give me a list of storage groups on an Exchange server. What might I say? I would say something like “get storage groups”. If I instead said “get storage group” you might reasonably ask me “which storage group should I get?”, but “get storage groups” makes it clear that I want all storage groups.

Apparently in the PowerShell design meetings a decision was made that the subject noun of the verb phrase that is each cmdlet would always be singular. Meaning, there is no get-storagegroups; to get the list of storage groups for a given server, you run get-storagegroup -server foo. To get a single storage group you run get-storagegroup -identity foo\bar.

But it’s not just the Exchange cmdlets that have this problem. When you want to get a list of available PowerShell cmdlets, what do you run? No, not get-commands; you run get-command. In fact, as far as I can tell there are _no_ commands which incorporate a plural subject. It’s a minor gripe, I know, but it shows PowerShell’s shittiness in microcosm.

23Aug/074

First of many PowerShell gotchas

Now that I’m in PowerShell Hell, I’m trying to figure out how to do some basic tasks, like get the list of storage groups and mailbox databases on a given Exchange 2007 server. Here’s my first attempt:

    $ex = get-exchangeserver -identity exchange2007
    # $ex | get-member
    write-host "ExchangeBuild: " $ex.ExchangeVersion.ExchangeBuild
    write-host "AdminDisplayVersion: " $ex.AdminDisplayVersion

    foreach ($sg in get-storagegroup -server "exchange2007") {
        write-host " SG: " $sg.Name
        $dbs = get-mailboxdatabase -storagegroup $sg
        foreach ($db in $dbs) {
    #        $db | get-member
            write-host "  Mailbox DB: " $db.Name
            write-host "  Mailbox DB Disp Name: " $db.AdminDisplayName
        }
        $dbs = get-publicfolderdatabase -storagegroup $sg
        foreach ($db in $dbs) {
    #        $db | get-member
            write-host "  Public Folder DB: " $db.Name
            write-host "  Public Folder Disp Name: " $db.AdminDisplayName
        }
    }

That produces this output on my Exchange box:

    ExchangeBuild:  8.0.535.0
    AdminDisplayVersion:  Version 8.0 (Build 685.24)
     SG:  First Storage Group
      Mailbox DB:  Mailbox Database
      Mailbox DB Disp Name:  Mailbox Database
      Public Folder DB:
      Public Folder Disp Name:
     SG:  Second Storage Group
      Mailbox DB:
      Mailbox DB Disp Name:
      Public Folder DB:  Public Folder Database
      Public Folder Disp Name:  Public Folder Database

Note how First Storage Group seems to contain a nameless public database, and Second Storage Group contains a nameless mailbox database. In fact, First has only a mailbox DB, and Second only a public DB. WTF?

Try the code this way:

    $ex = get-exchangeserver -identity exchange2007
    # $ex | get-member
    write-host "ExchangeBuild: " $ex.ExchangeVersion.ExchangeBuild
    write-host "AdminDisplayVersion: " $ex.AdminDisplayVersion

    foreach ($sg in get-storagegroup -server "exchange2007") {
        write-host " SG: " $sg.Name
        foreach ($db in get-mailboxdatabase -storagegroup $sg) {
    #        $db | get-member
            write-host "  Mailbox DB: " $db.Name
            write-host "  Mailbox DB Disp Name: " $db.AdminDisplayName
        }
        foreach ($db in get-publicfolderdatabase -storagegroup $sg) {
    #        $db | get-member
            write-host "  Public Folder DB: " $db.Name
            write-host "  Public Folder Disp Name: " $db.AdminDisplayName
        }
    }

which yields:

    ExchangeBuild:  8.0.535.0
    AdminDisplayVersion:  Version 8.0 (Build 685.24)
     SG:  First Storage Group
      Mailbox DB:  Mailbox Database
      Mailbox DB Disp Name:  Mailbox Database
     SG:  Second Storage Group
      Public Folder DB:  Public Folder Database
      Public Folder Disp Name:  Public Folder Database

That’s more like it. What’s the difference? In the version that doesn’t work, I do this:

 $dbs = get-mailboxdatabase -storagegroup $sg
 foreach ($db in $dbs) {
     ...

and in the version that does work, it’s:

 foreach ($sg in get-storagegroup -server "exchange2007") {
     ...

What’s the difference? Well, if you’re like me, you’ll say “there’s no difference; they’re equivalent”. Ah, but there’s where your wrong. You, like me, are assuming get-mailboxdatabase returns something like a List object, which has zero or more entries in it, so when you foreach over this list object, if there’s nothing in the list, the loop won’t iterate. However, that’s not what’s happening. When get-mailboxdatabase is evaluated and returns no items, the result isn’t a zero-element list but some sort of special-case ‘nothing’ value. Then, foreach ($db in $dbs) is treated as ‘for each nothing value in nothing value, do whatever’.

Have I mentioned how much I hate PowerShell?

23Aug/071

Goddamit Microsoft, what did I do to deserve this!?

It’s been established that I think PowerShell is a mistake. Now, it seems, I’m being punished for my blasphemy with additional programming shitwork. But first, some backstory.

At AppAssure, we have a lightweight backup agent that sits on Exchange servers and interacts with our backup server product to backup and restore the Exchange environment. One of the things that agent does is communicate with Exchange to determine what storage groups it has, where the EDB files are located, and so on. The agent also handles dismounting and remounting storage groups when doing a restore.

To accomplish these two things, we use the CDOEXM library, which is an in-proc COM server used by generations of programmers to automate Exchange tasks like ours. It’s worked well for us for over a year now, with no problems whatsoever.

Apparently, this handy, reliable bit of code came to the attention of the Microsoft Exchange team, who of course had to take corrective action lest the world begin to think that Microsoft software isn’t all blue screens and talking paperclips. And so it is that, starting with Exchange 2007, both CDOEXM and the Exchange WMI providers are dead, no more, ceased to be, etc.

Here’s this from the horse’s mouth:

CDOEXM was used to develop applications that manage the Exchange 2003 store. CDOEXM is not available in Exchange 2007 and has been replaced by the Exchange Management Shell. Existing applications built using CDOEXM cannot manage Exchange 2007 servers.

Then there’s this document, which says this about the Exchange WMI providers:

Retain a computer that is running Exchange 2000 or Exchange 2003 in the Exchange 2007 organization if you need this functionality.

And before you Microsoft fanboys get all huffy and point me to the CDO 1.2.1 download, pull your head out of your ass and pay attention for once. This download gives me CDOEX, but I don’t want CDOEX, I want CDOEXM, the ‘M’ standing for ‘Management’; you know, things like mounting and dismounting storage groups.

Now, in case you didn’t understand all of that, here it is in layman’s terms: I (and no doubt thousands of others) have written scripts, applications, utilities, etc, using the interface that Microsoft published and cheered on for years. Now, starting with Exchange 2007, that interface isn’t just ‘discouraged’ or ‘deprecated’ or ‘soon to be obsolete’; it’s fucking GONE. There’s not a single fucking bit of code written for Exchange 2003 that will work with Exchange 2007. That is what is known in my field as a ‘breaking change’, or more colloquially, ‘fucking bullshit’.

So, what does this have to do with PowerShell, you ask? Well, guess what the new, preferred, only-option interface is to Exchange 2007? You guessed it: PowerShell! There are all these great Exchange 2007 cmdlets (yes, I know, just saying ‘cmdlet’ makes me a little bit gay), that do everything you could possibly want. Of course, that only works for Exchange 2007, so if you also want to support Exchange 2003 (which, incidentally, is the version most shops are still running), you’ll have to maintain two sets of Exchange interface code, one for E2k3 and one for E2k7, with the E2k7 version being managed code.

So that is my lot. I have to keep the body of E2k3 code we’ve already written, because few Exchange admins have been foolish/brave enough to pull the trigger on E2k7, while at the same time writing new E2k7 code to cover those brave/foolhardy few who have pulled the E2k7 trigger, and those who will in the near future.

I’m sure there’s some rational, plausible, reasonable explanation for fucking over legions of Exchange scripters and tool builders. Maybe E2k7 is such an earth-shattering qualitative upgrade that the legacy APIs just couldn’t be sustained. Or maybe it was too much effort for the Exchange team, and would’ve diverted valuable resources away from VoIP or IM or one of the other bloated shovelware features chucked into E2k7 that no one will use.

It doesn’t fucking matter what the excuse it. Coz MS has a monopoly on office collaboration software, so they can fuck you however they want. What’re you gonna do? Explain to the CEO why he can’t use Outlook anymore, and how sendmail is so much better? Yeah right. No, you’ll just keep eating whatever shit Microsoft feeds you, because that’s the order of things. Meanwhile, I’ll add additional cruft to my product just to keep it working with the latest MS tools, when I could’ve spent that time implementing new features, or sleeping.

Someday, Microsoft won’t have a stranglehold on corporate software. Someday, the proletariat will rise up against the capitalists who control the means of production, and a revolution will sweep the earth, leaving in its wake blood-soaked fascist EULAs and shattered Vista Premium Ultra Super Best Edition DVDs. Someday. For now, we do what we’re told and bend our backs to the will of our master. And I’ll hack PowerShell code whilst muttering to myself about ‘goddamned cmdlets’. Viva la Revolution!

Oh, and for what it’s worth, you can invoke PowerShell cmdlets from within C#. It’s only about fifty lines of code, too. Trust me, it’s better this way.

22Aug/072

WTF is Powershell For?

Recently my day job has forced me to examine a product which exposes a number of Windows PowerShell cmdlets (cmdlets being the astonishingly lame term for executable verbs exposed within PowerShell; if you weren’t gay you would refer to them as ‘commands’). The details aren’t important; what’s important is that PowerShell is among the most misguided developments in Microsoft history.

The idea is that PowerShell takes the proven UNIX shell idiom of small executable tools connected by piping text output from one to the input of another, and updates it for the object-oriented, .NET world. Now, instead of running the output of ps through awk to find memory hogging processes, and piping awk‘s output to kill, like this:

ps -e | grep " p" | awk '{ print $1 }' | xargs kill

you can do shit like this:

get-process | where { $_.WS -gt 10MB } | stop-process

You see, get-process returns a set of Process objects, while where lets you filter those objects by property values like WS (working set size), and that filter produces a filtered list of Process objects, which are piped to stop-process which kills the processes represented by any Process object it gets.

As a programmer who also uses the UNIX shell, I think this kicks ass. It’s a very neat combination of the proven pipe idiom with stronger typing and object-orientation. There’s just one problem; it’s not for programmers. It’s for ‘IT Professionals’, with its ‘admin focused scripting language’. Right.

As someone who has both been and worked with ‘IT professionals’ and ‘admins’, let me assure you that most of them are stupefyingly clueless. A few can handle simple batch files, and one or two that are about to quit and become programmers might handle Windows Scripting Host. Very, very few will be able to handle PowerShell. It’s not their fault. They’re not programmers, so why should they be expected to code like programmers? I dunno; ask Microsoft.

Delicious Bookmarks

Recent Posts

Meta

Current Location