Joe White’s Blog

Life, .NET, and Cats


Archive for May, 2004

Spammer Sentenced to 7 Years in Prison

Friday, May 28th, 2004

Alas, the prison time isn’t actually for sending the spam; it’s for the forgery, identity theft, and falsifying business records that he had to do in order to send the spam. But hey, whatever gets him off the streets. I just hope they don’t give him any Internet access from prison.

Here’s the news article.

Code Coverage

Friday, May 28th, 2004

NCover may be worth a look. In my copious spare time. Code-coverage analysis could be a Good Thing ™ for test-driven development. (Apparently the people who wrote NCover thought so too.)

Actually, there are two apps out there that are both called NCover. One is on SourceForge and the other is on GotDotNet Workspaces. The SourceForge one has a sample report on their Web site (showing its own test coverage) that looks pretty tempting, but the GotDotNet one has Visual Studio integration. Both projects seem fairly active.

Here’s a post from the csUnit mailing list on how to use the GotDotNet NCover with csUnit.

If I ever get around to trying either one, I’ll post my experiences here. (Has anyone else tried either or both of them?)

Cats, music, and high-school English

Tuesday, May 25th, 2004

(Warning: This one is a little sappy.)

Today has been a pretty good day.

Things went fairly well at work; we didn’t get Milestone 1 out today like we’d hoped, but we’re darned close. Then Jennie called me and said we needed to take Noel, our youngest cat, to the vet to make sure she’s okay (she’s put on quite a bit of weight in the week or so she’s been on medication, and has been kind of listless).

Noel didn’t mind getting into the cat carrier, but she really didn’t want to come back out of it once we were in the exam room at the vet’s office. After we had managed, with difficulty, to extricate her, she just sat there on the steel table, all huddled and pitiful, for the ten minutes or so until the vet came in to check her out. I just kept petting her and reassuring her and trying to soothe her, not quite sure if I was really doing any good or not. She didn’t make a sound the whole time we were there.

As it turns out, she’s fine. The vet checked her out to make sure the weight gain was normal, and not fluid buildup or anything like that, and then recommended that we cut the dose of her meds. When it was time to go back home, I wasn’t too surprised that Noel was again willing to get into the cat carrier.

And I must have been more worked up than I’d realized. I was pretty tense on the way home, probably from seeing how scared Noel was in the vet’s office. I was downright jittery. I lucked out on music, though — after a few repeated loops through the 17 radio stations I listen to on a regular basis (really — I just counted them), I hit one that was playing “Walking in Memphis”. Today, that was what I needed. Mellow, but raw and powerful. We’ve had the CD for years, and there’s some great stuff on there; it’s long been a staple on roadtrips. He writes real music, not the fluff that’s most of what’s out there. Music with some real soul. Fluff has its place, but sometimes you need the real stuff. It helped.

It was a beautiful night out, so after I got home, I put on long sleeves and went out for a walk. I’ve been doing this, long walks in the night air, since my high-school days, and it can really help clear my mind and let me shake off the stress of the day. Doesn’t always work if there’s too much stress already, which has been the case for altogether too long now, but tonight was good. Like I said, it’s been a pretty good day.

As I walked, I found myself thinking about all sorts of things: neighborhoods back home in Cedar Rapids; the playground at my elementary school; Halloweens come and gone; the smell of the dew in the morning on the summers I went to camp. And I thought about a class assignment back in high school English class.

I’m not quite sure why I remember this particular assignment, after more than ten years. It was an in-class exercise; everyone wrote down what they would have to do to consider their life a success, and then we went around and shared what we’d written.

I could have said I’d consider my life a success if I had a six-figure income, or if I owned a fancy house. I could have said I wanted to own a horse (but I wouldn’t have; I’ve been to horse ranch camp, and I found out that horses are a lot of work). I could have said I wanted to be a policeman, or a pilot, or an astronaut, or President of the United States. I could have said I wanted to be a published writer, or a well-known musician. I could have said I wanted to own my own business. I could have said I wanted to be a famous inventor. I could have said I wanted to get a part in a stage play. I could have said I wanted to win marksmanship trophies, in firearms and/or bow-and-arrow. I could have said I wanted to go hang-gliding at least once. I could have said I wanted to find a church that I felt comfortable in. I could have said I wanted to get married, settle down, and raise happy, well-adjusted kids.

I could have said any of those things, and those, in fact, were generally the sorts of things that the other people wrote. Those are all things I’ve wished for at some point or other, and that’s not counting childhood fantasies (well, I guess astronaut and President were probably childhood fantasies, but the rest are for real). I’ve even, at this point in my life, achieved a whopping two of them: I’m happily married, and I’ve found a great church where people believe things that make sense.

But somehow, I didn’t approach the assignment from that angle. That happens to me sometimes, where I come at something from a funky viewpoint without even realizing I’m doing it (and then wonder why it’s turning out to be so hard).

I don’t remember the words that I wrote, but it was something along these lines: I will consider my life a success if I give it a good shot. If I stand up for what I believe in. If I can look back and not be ashamed of the choices I’ve made.

I remember feeling kind of silly when the other people read theirs. Oh, I thought. Yeah. That’s what the assignment was really supposed to be. Where did I come up with this?

Part of why I wrote what I did is that life is short. I don’t want to say “I won’t consider my life to be successful unless I’m a published writer”, because if I died tomorrow, then my life would have been a failure. Which is so obviously wrong that it never even occured to me to write anything of the sort.

But even knowing that, I felt kind of silly at the time.

For some reason, that assignment wandered back into my memory tonight. And I think, looking back, that really, I was on the right track. And all things considered, I think I still am.

Delphi/Win32: Fun with RTTI

Monday, May 24th, 2004

In .NET, it’s easy to use Reflection to peek into other objects’ private fields (though it’s considered bad form, and of course it requires full trust). But doing the same thing in Delphi/Win32, as far as I knew, involved using the Disassembler window to find some magic numbers, and then hard-coding those magic numbers, which would be nastily brittle (and is why I never bothered).

Not necessarily so, as it turns out. Hallvard Vassbotn just posted about a Delphi/Win32 hack to write to a read-only property, using nothing but RTTI, a nice twist on inheritance, and of course some pointer arithmetic — but no hard-coded magic numbers, so it’ll still work even if you change ancestors or add more fields. Cool!

Security permissions in Windows Forms

Sunday, May 23rd, 2004

Whenever I’m writing a custom WinForms control, unless I have some reason to do otherwise, I always try to write it so it’ll work in a partial-trust environment, like embedding the control inside a Web page (Internet zone), or running a program from a network drive (Intranet zone).

Windows.Forms does not tend to make this easy.

So I’m working on my FlowLinkLabel class, right? There’s some text (blue and underlined, of course (well, by default anyway)), there’s possibly an image. And depending on the length of the text string, there may be a bunch of empty space to the right of the text, or below the image. I don’t want the control to react to clicks in that empty area. Only clicks on blue underlined text (or on the image) should count. Okay.

That means I need to do my own click tracking; I need to override OnMouseDown and OnMouseUp. No problem. I also need to process WM_CANCELMODE. Problem!

If the user presses the left mouse button, and then (without letting up on the mouse button yet) Alt+Tabs away, or presses the Windows key to bring up the Start menu, or some ill-behaved application steals the focus because the user just got an instant message, then my OnMouseUp handler will never fire. But I still need to clear my “_isLeftButtonPressed” flag. Granted, if I can’t clear that flag, it will only cause real problems in certain pathological edge cases. But I don’t like leaving edge cases open, even pathological ones.

As I learned back in my Delphi days, Windows tells me about all these rude happenings by sending me a WM_CANCELMODE message. Lovely, says I. I’ll just override WndProc and — boom! Oops, there’s a security demand on WndProc. If I override WndProc in FlowLinkLabel, then nobody in the Internet zone can instantiate FlowLinkLabel. If they try, they get a SecurityException.

The interesting part is this: The SecurityException is not thrown by the call to new FlowLinkLabel(). Instead, it’s called when the Just-In-Time compiler tries to JIT the method containing the call to new FlowLinkLabel(). That is, it blows up when it’s partway through trying to JIT-compile InitializeComponent. Which means the exception’s stack trace is marvellously unhelpful; all I see is that an exception occurred in the Form1 constructor, on the line where it tries to call InitializeComponent. I never see anything that tells me which line within InitializeComponent is actually causing the problem, heavens no; so if this is the first time I’m trying to run my app under restricted permissions, I don’t have a clue which third-party component is being ill-behaved. Nice, eh?

Back to FlowLinkLabel. I can’t override WndProc if I want partial trust to work. I was getting started on an elaborate workaround, and then happened to be looking through Reflector and saw that Control.WndProc calls something named OnNotifyMessage. I fire up the help, and read that OnNotifyMessage is specifically meant for partial-trust scenarios! It can’t modify or suppress the message; all it can do is watch the message going by. Which is exactly what I need for WM_CANCELMODE.

Lovely, says I. I’ll just override OnNotifyMessage, and do the appropriate SetStyle() to tell WinForms it’s there. Run it under the Internet zone — it runs! Hooray! Write some more code. Run and — boom!

Undo checkout. Was it my override of OnMouseDown? Try that again, see what happens. No exception. Well, I know it wasn’t my override of OnNotifyMessage, I already tested that. Try again anyway, just to make sure. Hmm. Scratch my head. Finally go through all the motions again, testing much more often this time.

It’s when I add an if statement inside OnNotifyMessage. An if statement that does nothing but read the message struct’s Msg int property.

Open Reflector again. There’s a security demand on the Message structure. It requires unmanaged-code permissions. Which I very much do not have in the Internet zone.

So they give me a method I can override where I can see all these messages flying by. But I can’t see a blooming thing of what’s in those messages. That is frustration in action, folks. It also smells like poor design — OnNotifyMessage exists only for partial-trust scenarios; the docs even go so far as to say you don’t need to bother calling base.OnNotifyMessage(), which heavily implies that Microsoft will never, ever bother to put any of their own code into OnNotifyMessage. And aside from permissions, anything you can do with OnNotifyMessage can be done just as easily by overriding WndProc. OnNotifyMessage exists for one purpose, and yet, it’s useless for that purpose.

Sigh.

I worked around it. The first time FlowLinkLabel.OnNotifyMessage is called, I enter a try..except, where I call another method that tries to read message.Msg (has to be a separate method, since it’s the JIT throwing the exception — if I did it inline, my try..except would never finish getting JITted). If a SecurityException is thrown, I just don’t watch for WM_CANCELMODE anymore, and those pathological edge cases remain open. But any time it turns out that the code can read message.Msg, it will process WM_CANCELMODE quite happily. (Then, of course, I short-circuit my implementation on later calls, so I’m not throwing an exception every time a Windows message is received.) Decent compromise, I guess.

Windows Services in .NET (with Indy)

Saturday, May 22nd, 2004

As part of my team’s project at work, we had to create a Windows service in .NET. Originally we built it in Delphi 8 for .NET, which worked fine as long as we could get the compiler to cooperate. But the D8 compiler is so buggy, especially when working with multi-assembly project groups, that we eventually wound up porting the service back to C#. Sigh.

Creating a Windows service in .NET is actually not too hard, though it isn’t well documented. If you have Visual Studio, there’s actually an option in File > New Project to create a Windows service. However, that doesn’t do everything you need; specifically, it doesn’t give you any way to install your service so that Windows will actually run it (or show it in the Services snap-in so you can start and stop it later). And if you have Delphi 8, you don’t have a Windows service wizard. (There was one in D6, but apparently its .NET rewrite didn’t make the D8 release schedule.)

This article on CodeProject was invaluable to us in getting things up and running. It shows how to build a .NET Windows service from the ground up; it doesn’t assume that you have Visual Studio with its Windows service project wizard (which is handy if you’re using Delphi 8, or if you only bought Visual C# instead of the full Studio, or if you’re writing your code in SharpDevelop or Notepad). It also shows how to install (and uninstall) the service using installutil.

Once you’ve walked through the article, and have your service up and running, it’s pretty slick. The service ends up as an EXE that’s intended to run under Windows’ service manager — and the .NET service plumbing will automatically give the user a meaningful error message if they try to run the EXE manually (though there is about a 15-second pause first), which is good. And if your service is starting an HTTP server using the open-source Indy networking libraries (check them out if you’re still using the wussy FTP and HTTP support in System.Net — Indy is better, and it supports just about every Internet protocol known to man, both client- and server-side, and it’s free), then you don’t even need to worry about the fact that there are something like three threads being created and juggled just to manage your service — it just works. Just set the server’s Active property to true in your override of ServiceBase.OnStart, and set it back to false in your override of ServiceBase.OnStop. Indy will even wait for any pending HTTP requests to finish before it returns from the Active = false setter. Very cool.

Merged cells in Xceed Grid

Friday, May 21st, 2004

My team recently did a survey of the available WinForms grid controls for .NET, and we pretty unanimously voted for the Xceed Grid. We miss some features from the Delphi world’s TMS grid, like fixed columns and merged cells, but TMS hasn’t shown any signs that they intend to bring their grid forward into the Delphi for .NET world and we needed something.

However, even though fixed columns aren’t natively supported in the Xceed Grid, they can be emulated. Actually, we let their sales folks know that we couldn’t buy their grid if it couldn’t do fixed columns (true), and they supplied a workaround. Which didn’t work in the 2.0 version, but they were kind enough to send us a pre-release version of 2.1 (then about two weeks away from release) and the fixed-column workaround worked again. (2.1 is now available.) It works great; you’d never know it was a workaround.

And they just posted a knowledgebase article on how to emulate merged cells. So at this point (though not having tried the merged-cell workaround), I think we’re not missing any features from the TMS grid, and we sure have a lot more features to play with. Pretty cool.

Political Link of the Day

Friday, May 21st, 2004

May offend some conservatives. You’ve been warned. 😛

George W. Bush and the Constitutional Contractors


Article on writing custom FxCop rules

Friday, May 21st, 2004

The FxCop team has posted an article on how to write custom FxCop rules.

Man, I really need to dust off my FxCopWiki and take it live. This would be a great link for the wiki.

Charlotte’s Web Search

Thursday, May 20th, 2004

Allen Bauer just posted about the fate of “Charlotte”. Apparently it hasn’t been developed further as a product, but parts of it have wound up in the CodeDOM system in C#Builder and Delphi for .NET.

So as I read his post, I was scratching my head and wondering what “Charlotte” was.

A brief Google search for borland charlotte found a page on Dr. Bob’s site that briefly mentioned Charlotte as a scripting language for writing Web services. Now I’m really curious… it’s hard to hear about a new language (even one that won’t be released) and not even see any sample code. The sign of a true geek, I guess.

As it happens, that very same Google search also turned up this very interesting page: “If ever a story called for further reporting, this one did.” The fact that the word Charlotte appears in this story is apparently just a coincidence, though an amusingly appropriate one.


Joe White's Blog copyright © 2004-2011. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS). Privacy policy