Saturday, September 24, 2005

Debugging and testing serviced components

I've been working over the past couple of weeks on a new data access component at work. For many and varied reasons I decided to implement it as a serviced component. I wanted to take advantage of COM+'s ability to pool and maintain objects, as well as its tried and tested transaction management capabilities for slinging stuff in and out of a SQL Server database.

Since we're using VS 2005 to develop this new project, I wanted to take advantage of the integrated Unit Testing tools that come with it straight out of the box to make sure my component was working as expected. It was here that I encountered one or two things that I'm noting here so I can remember them:

You'll never get good code coverage stats
One of the things that needs to be configured when you enable Code Coverage in VS 2005 is exactly which DLL's it's going to create code coverage stats for.

Unfortnately there are 2 things that prevent VS from allowing it for DLL's that contain serviced components.

  • COM+ only looks in the GAC

If you want COM+ to recognise your component and run it as a server component (as opposed to a library component - more in that in a minute) you must install it in the GAC. This is no biggie. You just open up you WINDOWS/Assembly folder and drag/drop your DLL into it. Job done (thanks to the Fusion shell extension). You can also use GACUTIL.exe, but isn't dragging and dropping so much easier?

So you've got you component installed in the GAC, you then need to register it as a serviced component. Easy. Just use REGSVC.exe and bob's your uncle. One serviced component, configurable through the Component Services management utility. Cool.

The problem arises, however, when you try to set up code coverage to get stats on your component. You can only reference DLL files directly, and by default the 'Select Artifacts to Instrument' dialog only incldes those DLL's in your solution.

You can add other DLL's to the list, but try to navigate to the GAC and add them from there, and no dice. It somply won't allow you. This is either an intentional feature, or a side-effect of Fusion. Although in real life, the GAC is organised as a bunch of folders with subfolders and DLL files within them, when viewed in Explorer (as in, for instance, the Open File dialog) the assemblies appear as assembly objects. Since these aren't actual DLL files, the dialog won't allow you to add them.

Oh well. I'll have a play about and see if I can't work out a way around it. I've got a couple of ideas, but they all generally revolve around changing the way the component is referenced, and as such, change the overall context in which the abject will be used. Change the test environment too much from how it's actually going to be deployed, and you've negated your tests - they're no longer valid. Some (and I really do mean a very small amount) things can be changed for the purposes of testing and debugging, but not too much.

  • Serviced Components don't run in the normal application context

Actually, this isn't strictly true. Serviced components can be run inside the context of the calling application. And it's really simple to do, too. On the property sheet for the COM+ Application you've created, under the 'Activation' tab, select 'Library Application'. This will create the objects created by COM+ in the context of the calling application.

This can even be demonstrated really easily - just step through some code that calls a serviced component you've made in the debugger. If the application's running as a Server application (i.e. objects are actually created and run in dllhost.exe, rather than in the calling app) the debugger will just step over that code. Press F11 all you like, it won't do any good. Because the object isn't in the same process as the app being debugged, it won't step into it. However if you change the configuration to a Library application, you will be able to debug to your heart's content.

So what's that got to do with Code Coverage? Well, (I think) VS only produces results for code running in the TestHost process, or the ASP.NET equivalent, if you configure it that way. So, even if I did manage to add the GAC'ed DLL, my code coverage stats would be poor. UNLESS, for the purposes of testing I configured the app as a LIbrary Application.

I guess you'd only need to do it the once, though. Once you know your unit tests cover x% of your component's code, you can configure it how it'd be in production and leave it - if you're using Team System you'll be able to publish the results and keep a record of the coverage stats to take away. Nice!

Ignore the error messages
Okay. Don't ignore the error messages, just don't drill down to fixing the exact problem in the message. Because when you're working with Serviced components, you're working with (at least!) 2 sets of technology, the COM+ stuff and the .NET framework. As a result, the errors that get caught and passed between the 2 can lose a little in the translation. I had several errors crop up with null references and invalid security priviledges. They were invariably caused by either not installing the DLL in the GAC, or forgetting to register the component in the first place. Doh! Still, it took a bit of investigating, and I spent a while looking through the code trying to work out what was wrong. Guess I learnt a bit of a lesson - It's not always just about the code you've written.

Remember which actual file's being loaded
I spent a while building, rebuilding and generally buggering about with the code the first couple of times I made significant changes to how the component worked. Either I spotted a mistake and corrected it, or I got rid of a method, or I added a method and tried to call it. Some of the corrections got me all confused since I'd made various changes to the behaviour, but the results weren't changing.

Or, I'd add a method, write some code to call it, and then get a Mising Method exception.

What was going on? It's obvious now that I've spotted it, and it's even more obvious after what you've just read about Unit Testing, but the wierdness was being caused by the DLL not being re-installed in the GAC. I'd rebuild, and then when the test app called that assembly, it wasn't the fresh up-to-date assembly being called. It was the assembly that I'd already identitfied as being wrong that was running.

Doh!

All in all, though, everything seems to be working nicely now, though. I just wanted to get some stuff to remember written down to help me remember it.

Jurt a quick plea for help, I wrote this pretty much off the top of my head. If anyone spots anything that's very incorrect, please drop a comment and let me know. Just to re-iterate, I certainly wouldn't take this post as gospel. They're just some things I wanted to make a note of, and generally thought I'd share.

Sunday, September 18, 2005

And... Breathe...

So I've been a bit busy over the past couple of weeks.

What have I been up to?

  1. Spent 2 weeks in Egypt
  2. Spent a week at work
  3. Went book shopping


Actually, that doesn't sound too busy at all. How come I feel like I haven't had 2 seeconds to sit and do anything? Oh well.

Doing some interesting stuff at the moment with System.EnterpriseServices and .NET remoting in C# 2.0. It's big fun, and if it all works, should make my life at work a bit easier. Nothing huge, but I'm currently replacing a web service with a remotable serviced component. The web service works fine, but because of the job it does, it needs to be as quick as possible. WebServices are great for a whole host of reasons, but for out purposes it could be better. It's a logging component for our intranet, which can be called across sites, but always to and from applications we've written.

There's no need for it to be interoparable over multiple environments (one of the biggest advantages of WebServices). As a result, one of the first advantages remoting has over WebServices is being able to send messages over TCP, and serialized using .NET's BinaryFormatter. This makes the messages going backwards and forwards much smaller. I haven't get any data on actual message size, but it took approximately 8 times as long to pull a dataset out through the webservice than it did to pull the same data out as business objects through a remoted component.

Add to that the nice things that COM+ brings to the table like JIT Activation, transaction management and object pooling and it should be a nice replacement.

And I get to play with C# and VS 2005.

What more could a boy want?

I'm sure I'll be writing more about my adventures in C# 2.0 shortly, but for now, I've got a couple of new books to read (this, this and this).

Just wanted to share.

Saturday, September 03, 2005

Very Very Quick...

...Before Mrs Mawoo finds me...

I'm currently blogging from a hotel lobby in Luxor, just about half way down the east coast of Egypt. I'll write more when I get back in a week or so, but here's a summary:

  • Egypt rocks.
  • Luxor rocks.
  • Aswan rocks
  • Pyramids rule.
  • Temples kick arse
  • The desert's ace
  • You can have too much of a train trip
  • Cairo doesn't rock.

I'll elaborate further when I've re-learnt how to type (funny how you can get out of practice with these things ;-)) But for now, I'm in Egypt. And that's cool.

Just wanted to share. I'm sure one day I'll get onto some .net stuff again one day...

Sunday, August 21, 2005

The perils of stubbing out methods

I only have a single-thread brain. Sad, but true. I can only really concentrate on one thing at a time.

For example, when I'm writing, I like to stub out sections of code so I can some back and flesh them out when I've finished something else. Take thei example of some code in process:

Public Function GetString(AllTheString as Boolean) as String
    If AllTheString Then
        Return "You asked for all the string"
    Else
        'Add the 'Not-All-The-String' in a minute.
        'Why not make a coffee?
    End If

You get the point. I can deal with the other path the code can take at some point in time. Perhaps after a coffee. However, this approach doesn't work in SQL Server 2000. I'm sure it's well documented and whatnot, but it really did give me some grief earlier today. Take this example:

CREATE PROCEDURE ThisIsATest
    (@TestValue int)
AS

IF EXISTS(SELECT TheKey FROM TheTable WHERE TheKey = @TestValue
BEGIN
    INSERT INTO AuditTable(Event, Time)
    VALUES ('This value was found: ' + @TestValue, GETDATE())
END
ELSE
BEGIN
    /*I'll worry about this part in a minute
    I quite feel like a coffee roundabout now...*/
END

Hit the 'Validate SQL' button, and it'll return an error. A nice error? A helpful error? An error that might vaguely suggest that you might have a code path that doesn't actually so anything? No. What does it come back with?

Incorrect syntax near the keyword 'END'

Pointing at the last line of the script.

Took me ages of sifting through a long SPROC before I realised that was what it was trying to tell me. Bugger. All I was trying to dso was vlidate the SQL I had writen so I could move on to the other part.

Just wanted to share. Apologies for irrelevance and brevity, but it's late. All because of this very thing!

Saturday, August 13, 2005

Firsts, firsts and more firsts...

We're just starting a new project at work for the next few months. It's a fairly standard data mangling app, retreiving deatails about people, updating them stashing them back in a database. Nothing really out of the ordinary.

Well, it would seem that my team doesn't like to do the same thing over and over again (fair enough, neither do I!) so we're going to be doing a whole bunch of stuff that none of us have ever really done before. Our next project will be:

  • Written in C#
  • v2.0
  • in VS 05 beta
  • All developed on virtual PCs
  • Managed by Team System (Also running on a virtual server)


It's times like this that I really like not being chrged for by the hour. We had a meeting yesterday where we kind of figured that we can get the data-mangling parts written relatively quickly, so we could spend a bit more time doing nice twiddly bits for the UI. Nice. So there's going to be a few AJAX-easqe bits (I'm not even going to pretend that it's a new thing, but I'd never found a library quite as nice as Michael Schwarz' AJAX.NET for making it happen). IN real life, I;m sure we could knock something very dull rogether in a few weeks, but that would be it. It would be a very boring bit of kit. Just another in a long line of data mangling applications, And if I was being charged for by the hour, I'm sure that would suffice ('I don't care how boring it is, just do it as quick and cheap as possible!').

But I'm not. And that's cool. We get to learn new stuff (none of us have written in C# before) use new things (all betas, which is why we're doing it all on VPC's) and have some real fun (if you're into that sort of thing) with it.

Nice!

Just wanted to share.

Saturday, August 06, 2005

Disaster at Benjimawoo Towers!

Of all the keys that had to stop working after my little bit of clumsiness a couple of weeks ago why did it have to be F11!

Yes, I know I can change the default key bindings, but i'm too lazy to change them from the VS defaults and reconfigure every time I rebuild.

Grr! Just wanted to share.

Friday, August 05, 2005

Short-circuiting comparisons

This was one of those things that I read about and though 'Huh. When am I ever going to use that?' Turns out it's pretty useful at times.

VB.NET can short circuit comparisons using the AndAlso an OrElse keywords.

What's short-circuiting?
Short circuiting occurs when you have multiple comparisons on a line and the outcome is known before you get to the end of the line. Take the following line of code:
If 1=2 And 3=3 Then
'Do some stuff
End If


You know after the first part (1=2) that the comparison is going to return false, but the second part is still evaluated (i.e. the machine still checks to see if 3 does in fact equal 3). However, if you were to use this:
If 1=2 AndAlso 3=3 Then
'Do some stuff
End If


The machine skips the 3=3 part of the comparison. Just ignores it. It knows that since 1!=2 the result is going to be false, so it just skips over the second part.

So?
That contrived example doesn't look too useful. However, if we look at a real world example, all becomes clear:

Dim ds as Dataset = GetMyDataset()
Dim dr as DataRow = GetMyDataSet.Tables(0).Rows(0)
If Not IsDbNull(dr("FieldName")) And dr("FieldName") > 0 Then
'Do some stuff
End If


Because we're using the normal 'And', if the value in the row specified is null, the method will throw an exception because a value of type DBNull can't be cast to an integer. Although 'Not IsDbNull(dr("FieldName"))' returns false (because it is null) the second section is still evaluated. And because it's a null value, an exception is thrown.

However, if we use AndAlso, the comparison is short-circuited and it doesn't throw an exception:

Dim ds as Dataset = GetMyDataset()
Dim dr as DataRow = GetMyDataSet.Tables(0).Rows(0)
If Not IsDbNull(dr("FieldName")) AndAlso dr("FieldName") > 0 Then
'Do some stuff
End If


Because the first part of the comparison return false, the framework knows that the overall expression is going to return false, so it doesn't bother trying to evaluate the second part, and it doesn't throw an exception.

Needless to say, OrElse works in exactly the same way, but for Or's rather than And's.

It's come in handy for me a couple of times recently, anyway.

Just wanted to share.

Monday, August 01, 2005

Weeping update...

Although the title sounds like something you'd take to the doctor, I thought I'd offer something of an update to the last post I wrote about cleaning out my dad's computer.

As one kind commenter wrote, "it is far more productive to think of possible solutions"

Now I'm not proposing that I'm going to put a stop to all the various different flavours of intrusive marketing out there (blog comment spam, IM spam and the great granddaddy of them all, email spam), but I can at least make a note of what I did to try an alleviate the problem somewhat for my dad.

First, let me set the scene.

I have a teenage stepsister, and my teenage stepsister is a great one for IM, file sharing (although, as far as I know, it's all legal now) and generally caning the net for all its socially worth. She is also, at the end of the day, a teenager. Bit impetuous, bit naive, and a little too quick to believe popups that claim that her computer could be running quicker if she installed widget x.

I also have a father. He, like a lot of fathers, just wants his computer for invoicing, perhaps the odd bit of emailing, banking, and that's about it. He also once uttered the immortal line "Why couldn't they just leave it at Windows 3.01? Didn't it already do everything everyone wanted?". Hmmm. Although the gist of it was more about how computers have been getting more complicated than he wants.

So, to summarize:

1 teenage daughter who wants to use her computer to keep up with her mates, but isn't too aware that there are bad people out there who want to user her computer for slightly more nefarious deeds.

1 mature guy who needs his computer for work, but really doesn't want to have to deal with any more stuff to learn just to get his books done, which he's been doing in the same way since Office 97. Oh yes, and he hasn't really got time (who has, really, in the real world) to supervise her every online move.

I see a problem. How to secure his machine without adding the need for any more management. In fact, how to secure his machine network-wise without any apparent change in behaviour (of the machine, not him).

Well, the most thorough (and my preferred method) would be to start from scratch, stash all the documents and data away somewhere and spend a good few hours installing and configuring the machine to be nice and safe from (at least some of the nastier) nasties. Lock everything down, disable all the non-essential services, do some admin-type bits like shift his data onto a different partition from his system bits, stuff like that, and have everyone running on a non-admin account. However, although most of that would cause no noticeable change in the machine's behaviour, bits and pieces would require management, or to put it another way 'More bloody work'.

I would (and did), however, rightly or wrongly, hold short of installing a second firewall. My thinking is that with all the ports and services disabled that aren't needed, Windows firewall will be sufficient. It sits nicely in the background and slots in nicely with the rest of Windows Security Center. It doesn't have the learning overhead of a separate application.

I also whacked on MS Anti-Spyware for exactly the same reason. Although it's just a lightly re-branded version of Giant's Anti Spyware, it does at least integrate nicely with Windows and doesn't seem like too disparate of an app to learn. It's still quite consistent with (particularly the newer parts) the rest of Windows XP. I think I said before, it's perhaps not the swankiest, but it does at least do a reasonable job.

Those were the easy parts. Now came the hard part.

I started with turning the computer off.

I heard someone say once that the biggest security hole in any system lies between the keyboard and the chair. Any system (yes, ANY) can be compromised when you've got a real person pushing buttons at the business end.

So the most difficult part was getting my stepsister to take a bit of responsibility for what runs on her computer. I told her about checking for mysterious processes running in the background, what to do if she found one, how to check if something malicious was running and how to get rid of it. I told her about the perils of hitting 'yes' when asked "Do you want to enhance your browsing experience?". I went explained at great length (you ever tried to talk to a 13 year old girl about 'nerd stuff' for more than 10 minutes?) about how firewalls work, and what they do, and generally tried to make her a bit more aware of what's out there trying to get in.

The last part is the make-or-break factor. Everything before it is almost incidental. I can have an iron-clad OS, be running behind a rock solid firewall and have every scanner known to man running checking everything's OK. However, just like vampires, if I invite nasty things onto my machine, they (potentially) get a free rein over my computer. And that's the bit I really need to work on.

Oh to have longer than a short and hectic weekend to do it all in!

Just wanted to share.

Thursday, July 28, 2005

I am weeping as I write this

So I'm down in Plymouth for a few days. My sister's getting married tomorrow.

With a couple of hours to spare, I thought I'd borrow my dad's computer and check up on a couple of things (news, bank balance, that sort of thing).

I think I've discovered why people get so het up, annoyed and paranoid about their computers and the internet.

Dad's on AOL. Which I can almost forgive. No, I wouldn't go near them with a ten metre cattle prod, but each to their own. And it does automatically configure your web browser and mail client for you if you can stand their proprietary clients for each. Which I can't.) That's not too nasty a problem, I just hate AOL.

However, sadly I haven't got time at the moment to fix all the other stuff that's wrong with this machine. I'm writing this blog entry at what's left of the bottom of the IE browser window, because there's some sort of weird toolbar blocking the rest of the screen, that doesn't even appear in the toolbars menu soI've got no easy way of disabling it. So far I've hidden:

The Google toolbar
The MSN toolbar
The Yahoo toolbar
Some sort of explorer bar-esque toolbar that appears at the bottom of the browser. Goodness knows what that's for.

I'm writing in 3 word bursts, because every few seconds there's yet another popup telling me about today's greatest deals, or asking me whether or not I want to buy some game (it didn't stay open long enough for me to have a look at what it was, I can tell you!).

The only reason I can manage to get 3 words typed in a row at all is because I've turned the Messenger service off, killing the millions of net sends a second I was getting. I've disabled it for good measure, just in case...

It's running SP1 at the moment, and I'm guessing that the only reason it hasn't got SP2 installed is that the constant alerts that Windows Update flashes up saying that there are (still) new updates downloaded and ready to install on this computer are being left unheeded.

UPDATE: I have just this seond learnt that 'Bargains.exe' has been forced to close down due to an error. That was a little irrelevant aside, but it's really annoying when spyware interrupts your day crashing.

I don't use the phrase Syphilitic Whore of Intarweb Beelzebub lightly, and it truly does take some doing to get me to even think it. But this machine really is a Syphilitic Whore of Intarweb Beelzebub.

Looks like my job for the weekend's been decided...

  1. Uninstall obvious spyware crap (Honestly, who doesn't smell a rat when there's an entry in Add/Remove programs called 'Internet Optimizer' or 'Select Cashback'
  2. Install ALL updates, SP2, and everything since AND MS Anti-Spyware (Yes, I know it's not the greatest out there, but it's easy to use and better than nothing)
  3. Sort out Startup apps (I'm sure there are some if not nefarious, certainly dubious apps starting automatically)
  4. Wash, rinse, repeat

With a bit of luck, not only will dad's computer run a little swifter, but it'll make it a darned site easier for me to blog from his house!

That's enough for now. I'm gonna shutdown before I see yet another popup and have to throw ths computer out the window. And then I think I'll have a little lie down. And a stiff drink. There is much work to do...

But do you know what the realy depressing thing is? I doubt anyone'll notice. Popups and toolbars taking up two thirds of the screen seem to be de rigeur these days. People accept them in the same way they don't notice people pushing to the front of the queue or how they don't notice when shop staff don't say thank-you or smile (come on, it's not that hard!).

Just wanted to share.

Sunday, July 24, 2005

Two more reasons to own a camera phone...

Nice Melons!
Nice melons Mrs Mawoo!