Friday, December 22, 2006

Congratulations Jim and James

Jim Holmes has posted that his book (Windows Developer Power Tools, co-authored with James Avery), is now out!

http://frazzleddad.blogspot.com/2006/12/book-is-ou...

I've read an early version of the book, and I can say that it is definitely a must-have.  Get your copy today (and then bring it to CodeMash in January to have it signed).

Thursday, December 21, 2006

Dan Ciruli's Pushup Challenge

Doh!  I've been called out:

http://westcoastgrid.blogspot.com/2006/12/your-new...

Dan Ciruli (that grid computing beast on the west coast) took on a New Year's resolution last January to do one pushup (and one sit-up/crunch) for each the day of the year.  For example, on Jan. 1, 2006, he did one pushup.  January 2, he did two pushups.  Today, being the 355th day of the year, he did 355 pushups!

What an animal.

And then, he had to go off and name a bunch of internet personalities (myself included) to take on this same crazy challenge for 2007.

Hmmmm.  Perhaps I will, my friend.... Perhaps I will....

CodeMash Update

CodeMash: January 18-19, 2007 at the Kalahari Resort in Sandusky, OH
www.codemash.org

The Early Bird rate of $99 has expired (fellow procrastinators: I'm sorry!).  The new registration fee is $149.

However, the Kalahari Resort has allowed us to continue the great deal on the hotel rooms ($88/night + tax for a "Hut" room) until 12/28, unless the hotel sells out before then.

So, for $325 + tax, you get to stay two nights at an indoor waterpark resort in the middle of January, plus attend CodeMash, which is looking to be THE EVENT of 2007 that you don't want to miss! 

In fact, two people from London, England (that's like this whole other country that's an ocean away from us) thought the same thing, and they are flying over just to attend!  Why?  One primary reason cited was because there is nothing like this event in Europe.

Jim Holmes, fellow conference organizer, user group leader, and friend of mine, summed the event up quite nicely in the following (which I have permission to plagerize):

I’m making one last pitch to you in the hopes of convincing you to register and attend this terrific event.

Why is CodeMash something you should consider attending?  You should strongly consider attending because you’ll have the opportunity to attend sessions and keynotes from some of the software development industry’s finest minds.  We’ve three keynote addresses from luminaries who have been motivating forces behind some of the most significant products, methodologies, and changes in the development industry:

 

  • Bruce Eckel – Internationally Recognized Speaker and Author of “Thinking in Java”
  • Neal Ford – Application Architect at ThoughtWorks, Recognized Speaker on Languages and Compilers.
  • Scott Guthrie – General Manager, Microsoft Developer Division. 

Other internationally-recognized speakers include:

 

  • Scott Ambler – Internationally Recognized Speaker and Author on Agile Development and Database Refactoring. 
  • Marry Poppendieck – Recognized Expert on Lean Development Methodologies. 
  • Jay Pipes – North American Community Relations Manager at MySQL. 
  • Bill Wagner – Expert on all things C# and author of “Effective C#”

If that’s not enough then consider that we’ve 40 sessions covering an immense range of technologies including .NET, PHP, Java, Ruby, and other platforms.  We’re holding sessions on design, architecture, testing, agile methodologies, and deep dives into areas of the technologies I just mentioned.  Some of the session topics include:

 

  • Curry Favor with Closures: An Introduction to Functional Programming in C# and VB.NET (Bill Wagner, Microsoft Regional Director, Microsoft MVP and author of “Effective C#”)
  • SOA as a Conversation (Ken Faw, Regional Practice Director, Perficient, Inc.)
  • The Productive Programmer (Neal Ford, editor “No Fluff, Just Stuff”)
  • Let NHibernate Be Your Data Access Layer (Dave Donaldson, Microsoft MVP)
  • Lean Software Development (Mary Poppendeick, internationally recognized expert on agile/lean development and author of “Lean Software Development”)
  • Maximum Velocity MySQL (Jay Pipes, North American Community Relations Manager, MySQL)
  • EJB3 – What’s New? (Joseph Faisal Nusairat, author of “Beginning JBoss Seam”)
  • Ruby on Rails for Java Developers (Rob Stevenson, Quick Solutions, Inc.)

CodeMash is a terrific opportunity for developers of all ilk in this region.  I encourage you to register and attend.  It’s a conference that should not be missed!

 

Also see Jim's post on the value proposition for management to send developers to events like this:

http://frazzleddad.blogspot.com/2006/11/why-conferences-matter-and-how-to.html

Saturday, December 16, 2006

New Type of Blog Comment Spam?

I'm starting to get comment spam like the following:

I see you put a lot of work into this one A. I respect it!! Good luck and keep up the good work. bruxelles hotel de previsioni tempo estate distillation de l alcool

(The underlined parts in spanish link to *.es websites)

I just thought it was an interesting tactic that they used....

Friday, December 15, 2006

Book Review: Foundations of WF

Windows Workflow Foundation (WF) is a key component of the .NET Framework 3.0, and comes from the collection of API’s that were previously known as WinFX. It provides a robust framework that can be incorporated directly into a .NET application in order to provide workflow capabilities that would otherwise be complex and time consuming to develop.

On more than one occasion in the past, I have had to build custom workflow capabilities for my applications to use. So, when it was announced that WF was to become part of the .NET Framework, I became very interested in figuring out how to use it instead of always reinventing the wheel.

Foundations of WF: An Introduction to Windows Workflow Foundation by Brian R. Myers is the first book that I have read through on the topic. Brian has a conversational style of writing that I found easy to follow. He includes a lot of screenshots and source code snippets to break up the text into smaller, more palatable bites. This book is sure to become one of my standard reference manuals on the topic.

One good thing about this book is that there are examples in both VB.NET and C#, so you do not need to translate syntax in your mind if you know only one of these languages. But, this also becomes a bad thing when trying to use this book as a reference.

I personally prefer a single language version of books because I find it distracting to repeat sections of content for the sole purpose of displaying a different language’s syntax. In addition, I recall a couple of places in this book where the C# section refers you to something that was described in detail in the VB.NET section. If you tend to read a technical book sequentially from front to back, then this might be acceptable. I, on the other hand, tended to skip over the VB.NET sections of each chapter since the C# sections were found immediately after.

Aside from the dual code issue, and some minor stylistic/creative decisions that he made in creating the demo source code (i.e., his method of padding a purchase order number with leading zeros makes me cringe every time that I see that snippet of code), I found this book to be a great companion to step me through the “Hello World” and beyond of WF.

You will not only learn what is required to use WF in your application, but you will also become exposed to the different types of workflow provided by WF, the various out-of-the-box Activities, how to create your own custom Activities, and how to deploy your workflow-enabled application. As a bonus, Brian also includes a chapter on using WF with Office 2007 and SharePoint (chiefly by means of a single example scenario using an InfoPath form).

Full Disclosure: A review copy of this book was provided to me by Apress.

Look for Auroras Tonight and Tomorrow

We're currently at the Solar Minimum, or the point in the 11-year solar cycle where the Sun doesn't really do too much.  However, there has been some strong activity over the past few days that have caused geomagnetic storming here on Earth.

A Coronal Mass Ejection (CME) passed by Earth yesterday, which started a strong GM storm.  This resulted in the Northern Lights being seen in lower Michigan and Ohio, and possibly even further away.

Another CME that resulted from a X1 solar flare on Dec 14 will reach our planet some time in the next day.  This will most likely enhance the storm levels again to the Strong, Severe, or possibly even Extreme levels.

For those of us not worried about keeping satellites in orbit, or maintaining a working electric power grid, this usually means that we can go somewhere dark (away from city lights) and look to the North for an absolutely beautiful display of nature.  Be advised that during particularly strong storms, you may need to look up, or even to the South (depending on your latitude) because the Auroras would have been pushed that far away from the magnetic poles.

Disclaimer: I have seen instances where an incoming CME completely halts all GM activity, so don't be surprised if nothing at all happens.  It's important to be patient when hunting the Aurora.  It's well worth the wait if you find an active display in session.

Tuesday, December 05, 2006

Blog about CodeMash and Win a Zune!

http://www.codemash.org/Blog4ZuneContest.aspx

Help us spread the word about CodeMash using your blog, and you could win a Zune!

There's about two weeks left to register and take advantage of the early bird pricing. $99 for the conference, and $88/night (+ tax) for the rooms. That's just an awesome price for an event like this, so don't miss out.

Besides the conference, you also get admission to the indoor waterpark at the Kalahari Resort in Sandusky, OH. In fact, many people are planning to take advantage of this by bringing their families for a little vacation in the middle of January!

Don't know what CodeMash is? Check out the site for information and a list of keynote speakers and sessions:

http://www.codemash.org

UPDATE: Note that CodeMash is not just a conference for people in Ohio and Michigan. Sandusky is located between Toledo and Cleveland, Ohio, and both of these cities have airports serviced by major carriers. CodeMash is a full-blown, multi-day conference with nationally-known speakers, and is not to be confused with a Code Camp or other similar event.

Hope to see you there!

tags:

Friday, December 01, 2006

SQL Server Date Trick

Need an easy way to truncate a SQL Server DateTime to just the date part (i.e., midnight of the day that is represented)?

You can cast a DateTime as a float, take the floor value of that in order to get an unrounded integer, and then cast that back to a DateTime. 

cast(floor(cast(@fromDate as float)) as datetime)

This works because almost any modern platform's datetime value is a floating point value that represents a number of days since an epoch date (with the fractional part representing the time of day).  Negative numbers are days prior to the epoch, etc.  So, trim off the fraction, and you have just days.


This is much cleaner than another way that I found in some stored procedure code which essentially subtracts the hours, minutes, seconds, and fractions of a second from a given DateTime...

Monday, November 27, 2006

You Never Know Who's Reading...

I found the following link to my blog today while checking out my referrer stats:

http://www.toledofreepress.com/?id=4326

Lisa Renee Ward, a prolific blogger about Toledo topics, picked up on AVIMH's 2-year anniversary announcement and included that fact in her "Blog It! Toledo" online column in the Toledo Free Press.

Sunday, November 12, 2006

OSU - Michigan Week

This is the week!  The annual rivalry between Ohio State and the University of Michigan will be played out on Saturday November 18.  It should be a very interesting game this year, with OSU being #1 in the standings, and Michigan #2 (both teams are undefeated this season). 

But, I have to be honest: that's about all of the sports facts that I know.

For me, this game represents bragging rights for the next year.  Not only among most of my co-workers, who actually live in Michigan by choice (yeah, what are they thinking?), but also between me and my wife, who has always been a Wolverine fan, despite living in the glorious land of scarlet and gray all of her life.

I have one particularly fond memory of OSU-Michigan week.  Back when I had a local office that was 7 miles from my house (instead of the current 80 miles), I also had control over the office infrastructure.  We had one particularly obnoxious U of M alumnus who was brave enough to drive down to Toledo on the Friday before the game.  We'll call this individual Erik, because that's his name.

Erik always makes it his mission to stir the pot, and this Friday was no exception.

We used ISA Server for the office firewall, which allowed me to set up all kinds of little rules.  One thing that I did was create a rule so that every so often, the firewall would refuse to load whatever internet web page that he was trying to get to, and instead take him to a locally hosted "error" page.  The particular page that I created was adorned with OSU-related stuff, and even played the OSU fight song.  Yes, my friend, we Buckeyes pwned him on that day.  DFWN

I've been lucky enough to have bragging rights for the past 2 years.  Let's make it 3 in a row!

Friday, November 10, 2006

CodeMash Registration is now Open!

There's been a few hiccups in getting the registration site live for CodeMash, but today, you are now able to register through the website!

CodeMash (www.codemash.org) is a fairly unique conference that will be held on January 18-19, 2007 at the Kalahari Lodge in Sandusky, OH.  It stands out from other conferences that I've attended because it is will be a cross-pollenation event, bringing together developers from many different technologies (Java, .NET, Ruby, PHP, etc) into one common forum. 

It is also completely organized by the developer community, acting as a non-profit entity.  This means that your registration fees (which are extremely low for a conference like this) are being spent on the conference (i.e., your meals, etc), and not as a means of turning a profit.

We toured the venue last week, and I was totally blown away.  I had no idea that we had this high of quality of a conference facility in Northern Ohio outside of major metro areas.  Sandusky is halfway between Cleveland and Toledo, and is probably better known as the location of Cedar Point, one of the best amusement parks in the entire world.  Kalahari is also an indoor waterpark resort, so it will be an attractive destination in the middle of January.

If you're interested in attending this conference, then you will want to register soon.  Not only do you have to worry about being shut out (registration is capped at 500 attendees), but also there is a time limit for making room reservations at a great price ($88 a night, which includes admission to the waterpark).

https://www.codemash.org/register.aspx

(If this conference sounds interesting to you, even if you can't attend, then please help to spread the word through your blog, or by telling a friend, etc).

tags: , , , , ,

Saturday, November 04, 2006

NetFX 3.0

Dustin Campbell and I were chatting the other day about the whole confusion behind the .NET Framework v3.0, and why they decided on that version number despite the fact that the core (i.e., the CLR) is remaining at v2.0.  He filled me in on a little nugget of information that I think, if entirely accurate [not that I doubt Dustin, but I doubt my ability to correctly remember everything that he said], should have been articulated by Microsoft in the first place to stop whiners like me from making such a big deal about the versioning.

It seems that all of the upcoming Orcas features that we've been calling "3.0" (LINQ, extension methods, yada yada yada) do not require anything new in the CLR.  The languages will have new compilers, but the new compiler will still generate v2.0 MSIL and metadata (i.e., they will generate CLR 2.0 assemblies). 

So, from that perspective, I can start to see why it's no longer important to tie the framework version number to the CLR version number.  It seems that the CLR is stable, and could effectively remain at the current version indefinitely without hindering the ability to add additional functionality to the languages (like LINQ and extension methods).

Wednesday, November 01, 2006

Mac Ads

Never been a fan of Apple's new series of ads.  I mean, they're very well done (kudos to the agency that thought those up), it's just that I'm on the opposing team. 

Apparently, Rory doesn't like them either.

tags: , ,

Thursday, October 26, 2006

CodeMash!

The CodeMash website is live!

You can now submit abstracts if you want to present and you can pre-register to hold your spot in line. Official registration should be open soon and will cost only $99 for a two-day event!

Bruce Eckel, Neal Ford and Scott Guthrie are all keynoting the event.

CodeMash – I’ll be there!

You can also download information about the event if you are interested in sponsoring.

Tuesday, October 24, 2006

Heartland User Group Webcasts

Upcoming Webcast: November 6, 2006 at Noon EST

Heartland User Group Webcasts
Functional Programming and LINQ - Shifting your object paradigm.

Bill Wagner – Ann Arbor .NET Developers

Join us for technical presentations by experts from around our the user groups in Michigan, Ohio, Kentucky and Tennessee. In this webcast, Bill Wagner will demonstrate the new language extensions in C# and VB.NET called LINQ.

The language features added for the Orcas release of C# and VB.NET start moving those languages out of their Object Oriented roots into the realm of functional programming. It’s a different way of programming. Rather than designing classes with behaviors and data, you create functions that take data as inputs and produce different data as outputs. That radical shift can lead to much simpler ways to express your designs.

In this session, you’ll see the new syntax in these languages, and how you can leverage those additions to create more concise programs in less time.

Registration: http://msevents.microsoft.com/cui/eventdetail.aspx?EventID=1032314537&Culture=en-US
Event ID: 1032314537

Upcoming Topics:
11/20 – Intro to Workflow. What’s all the Noise About? – Brian Prince, Central Ohio .NET Developers Group
1/8 – Web Services Software Factory – Mike Wood, Cincinnati .NET Users Group

Another Year Down...

Just a FYI to anybody keeping stats at home:  This blog turned 2 years old on October 22. 

Thanks go out to everybody who actually subscribe to and read my posts.  I don't think I'd be writing if I didn't have my 4 regular readers....  Well, 2 readers if you don't count my parents....

Thursday, October 19, 2006

IE7

I've been using Internet Explorer 7 as my primary browser for about 6 months now (various beta versions).  I've always been an IE fan, dating back to version 4--, actually preferring it over the various Mozilla flavors.  This probably has a lot to do with the fact that most of my clients standardized on IE, so any web application that I developed was targeted for that single platform.

I only had a few minor problems with the beta versions of IE7, so my experience has been excellent thusfar.  Yesterday, I downloaded and installed the RTM version. 

Perhaps it is simply a coincidence, but I've been noticing some weird problems now with my laptop.  For instance, it goes into sleep mode when I close the display.  More than once now in the past 24 hours, upon waking up, the laptop does not show the login dialog--just the wallpaper and mouse pointer.  The only thing that I seem to be able to do is power down and reboot.

Also, more than once, the browser has just seemed to stop responding for 1-2 minutes.  It doesn't allow me to switch tabs, or scroll.

I don't want to just blindly blame the RTM version of IE7 for these problems, but I find it strangely coincidental that they started after I installed this most recent update.

Tuesday, October 10, 2006

Trouble in MVP World

The Microsoft MVP program is a recognition award for leadership in the Microsoft-platform user community.  I'm not a Microsoft MVP, but many of my friends are.  Some things happened during the last round of awards (beginning of October) that make me question the intention and/or value of the program.

First, they awarded, and then rescinded the MVP status for Cyril Paciullo, the maker of Messenger Plus, a free addon for MSN Messenger that is also a distribution vehicle for LOP (nasty adware program).

http://www.networkworld.com/news/2006/100606-micro...

Next, they didn't renew the award for Jamie Cansdale.  Jamie wrote TestDriven.NET, which is probably one of the most widely used addins for Visual Studio by unit testing advocates everywhere.  The reason cited: Jamie violated the "MVP Code of Conduct" because he happened to make his program work with the Express SKUs (Visual C# Express, Visual Basic.NET Express, etc).   Or, at least this is the speculation of what the violation was.

http://weblogs.asp.net/nunitaddin/archive/2006/10/...

How to get disqualified as an MVP

Wednesday, October 04, 2006

ClickOnce/VS2005 Version Number Issue

This is not severe, but still annoys me every time that it comes up.  Look at this screenshot:

clickonce_issue

Here I have the project set up so that ClickOnce will automatically increment the revision number after each publish.  Well, something apparently is not working,  because it seems that at least once a day, I get "Version already exists on the server" errors.

Blah!  Is it me, or VS2005 that's at fault?  I'm going to blame the latter, since I never make mistakes.

Tuesday, October 03, 2006

Congratulations, Josh!

A good friend of mine in the Microsoft community, Josh Holmes, has made the jump and became a blue badge himself.  Congratulations!

Details from Josh himself: http://www.srtsolutions.com/public/item/143418

Monday, October 02, 2006

Photo

My work email account filled up (I hate quotas), so I had to find things to delete.  One was an email from Mokee containing a really neat picture of my Bubby (Evan) staring out of Mike's back door at the swingset. 

I simply titled it "Yearning"...

IMG_2309_cropped

(I think it looks great as my computer's wallpaper)

Saturday, September 30, 2006

Delegates

NWNUG'ers: I'll probably publish the NWNUG Introduces... Delegates screencast and article to the user group web site later this week. I'm still thinking about what format I want the followups to these presentations to be. Definitely an article format instead of just the PowerPoint slide deck, but still debating on the whole screencast thing (bandwidth and all).

If you attend the group, but missed the last meeting on 9/26, then what I'm referring to is a new Intro-level mini-presentation (30 minutes or less) that we're going to try to have at the start of each meeting. The artifacts from this presentation will then be made available on the website for future reference.

My new favorite Delegate trick (courtesy of Dustin, who raves about it just about every time that we get together):

somelist.ForEach(Console.WriteLine);

Console.WriteLine qualifies as an Action delegate! The result is that you can dump out an entire collection to the console with one line of code.

What is Your "Home Office"?

I think that most people who actually know me also know that I have two young twins who run around my relatively small house making all sorts of noise (and creating an equal amount of chaos, which I've come to accept). I don't have the space to dedicate an entire room as a soundproof home office, so when I <airQuotes> Work From Home </airQuotes>, it really means that I'm at a Panera Bread somewhere drinking the same cup of coffee that I purchased hours before. (Sidenote: Don't get me wrong--I loves their Turkey Artichoke panini and soups as well, so they've gotten plenty of my money for what little Wi-Fi I actually use).

Up to about 4 years ago, I had an actual office only 7 miles from my house. And then it moved to 50 miles away, and most recently to 80 miles away. Heading into the office on a weekend in order to get a little project work done is no longer feasible.

I'm wondering what other possibilities there are out there for a place to actually work. It would have to have exposed electrical outlets (so that I can keep my laptop charged), free Wi-Fi Internet access, and allow me to talk on my cellphone without getting "shushed". There should also be free parking, and restrooms nearby. ;-)

The public libraries around here qualify for almost everything except for the "talking on the cellphone" part. There are other restaurants besides Panera (i.e., Starbucks and even McDonalds), but Wi-Fi is typically not free.

What I really need (and this is one of those business ventures that I'll never have the time or money to pursue) is an office complex where I can rent an actual office by the day, week, or month if I need to. It would be targeted for all of us remote workers, and priced to be much more affordable than leasing a small office space. The building would provide the internet connectivity and even offer a phone extension that you can use. Oh, and like any real office, it should also have a watercooler and coffee maker for free coffee ("a penny saved is just a penny").

I know that there is something similar to this in Southfield, MI (for example), but I think it's more for providing a facade that you have an office rather than just giving a remote employee of some company a place to sit for a day. Besides, Southfield is as far away from my house as my current office, so that doesn't help my present situation.

So, anyways, with a lack of alternatives, it looks like I'll be heading to Panera in Perrysburg either this afternoon or tomorrow afternoon to get some things done. Can I get anyone a panini while I'm there?

UPDATE: As I sit here in Panera, I realize why I keep coming back here instead of just anyplace with wifi: Delicious soup, some light jazz playing on the speakers, and interesting people all around ("interesting" in both the good and bad sense). For an observer type like me, it's just a neat place to hang out and get some things done.

Friday, September 29, 2006

Browsing this Blog

Blogger's navigation kind of sucks. I experimented with a tag cloud (in sidebar), but the 3rd party provider of this service isn't as good as I had hoped.

The best way for someone to browse this blog is to use the monthly archives (also in the right-hand sidebar). That will give you all posts for a month on a single page.

I'll probably move the blog later this year and finally use dasBlog on a hosted server. Then I'll have a little more control over how content is displayed to the user (specifically surrounding navigation options).

Until then, enjoy catching up on my thoughts, plskthx! ;-)

UPDATE: I think I realized why I received a few complaints about it hard being able to navigate. In my template, I only had the Archive list showing for the main page and archive pages. So, if someone landed on a specific post, the monthly archive list would not be displayed. Whoops! Problem fixed. Dig away!

Wednesday, September 27, 2006

Unnecessary Error

Time to complain about an annoying feature in an otherwise awesome product: SQL Server Management Studio.

I opened a table today to do some editing of bit field data.  This is your basic Boolean (True/False) column in a database table.  SQL Server itself represents Boolean (bit) data as 0 and 1.

But, SSMS displays "True" and "False" for the field values.  Furthermore, while editing a bit field, it only accepts the words "true" and "false".

So, look at the error that pops up when I try to change a "True" value to false by entering "0" (which, I'll reiterate for clarity, is what SQL Server ITSELF requires for "false"):

StupidError

Tuesday, September 26, 2006

Me on an Episode of The Simpsons

I was recently an extra on the set for an upcoming episode of The Simpsons.  It was so much fun watching the filming process.  Homer is totally like his character in real life, and Lisa is quite the Diva! 

I had one of the grips snap a picture before they kicked us off of the set:

simpsons_char

See for yourself!

tags:

Thursday, September 14, 2006

New Windows Live Local Feature

I noticed today that there are now some drawing tools on the Windows Live Local scratchpad that allow you to draw polygons and lines right onto your map!  Cool!

Here's a map that I marked up.  Path #1 shows what my "commute" looks like if and when I go to my office (note that by policy, this is not supposed to be mileage that I can expense since it is considered a commute).  #2 demonstrates that even after a polygon is added to a map, you can still edit vertices if you need to.

newLiveLocal

These are groovy features, but one thing that I didn't like was that while drawing the line, there was no way to pan the map.  I'm not sure how that problem would be solved since panning normally involves mouse-down dragging, but it is definitely a limitation.  (I zoomed out to solve the issue, but this results in a lack of accuracy in placing the points).

Wednesday, September 13, 2006

Internet Explorer: RTL Address Bar

I love the "CTRL-ENTER" shortcut in Internet Explorer. 

That is, if you want to go to a www dot com website, like http://www.microsoft.com for instance, just type Microsoft in the address bar, and then press CTRL and ENTER at the same time.  The "Microsoft" will be wrapped with "http://www." and ".com".

Well, every now and then, I would mistype the CTRL-ENTER part, and the contents of the address bar would shift to be right-aligned (for Right-to-Left reading).  I could never figure out what keys I pressed, because it would always happen so fast.

This morning, I finally figured it out.  CTRL-Right Shift (the one right under the ENTER key) will shift to RTL reading order, and CTRL-Left Shift will return to LTR reading order.  Note that there's also a right-click context menu on the address bar combo box that allows you to do the same thing. 

Now I don't have to assume that my laptop is possessed by mischievous demons.

tags: , ,

XML Notepad 2006

My first experience with XML was in 1998, and at that time, there was an invaluable tool (so I thought) from Microsoft called XML Notepad that allowed Morts to visualize and edit the XML's data in a non-angle bracket sort of way.

The novelty of XML Notepad quickly wore off once the limitations were realized, and I found myself other tools, like XMLWriter and even Notepad, for subsequent XML work. 

Just today, I came across a blog post announcing that a new version of XML Notepad was released by Microsoft.  Neat!

I downloaded and installed the program, and then started it up.  My first impression was that this is still a Mort tool, just with more functionality.  It has a tree view of the XML structure, lots of pretty colors, and supports transformation using arbitrary XSLT files.  And, the Find functionality is loaded with advanced features, like Regular Expressions and XPath.

But, what I found missing was a true source view integrated right into the program (right now, when you View Source, it launches Notepad).  If they could have added a XML view that offered the text editing capabilities found in Visual Studio (including highlighting and IntelliSense), then this would be a lightweight yet fully capable tool that I would find myself using regularly.  Until then, I'm not sure what role it will fill in my life.

tags: ,

Tuesday, September 12, 2006

Can't Wait for Groove

I'm a huge fan of FolderShare.  It's a great way to automatically share a document library with a group of people, and still have those files available locally when you're offline.

I have yet to install and use Groove (will be part of the next release of Microsoft Office), but it promises the same FolderShare-type functionality for file sharing, but also adds onto that the normal collaboration features that you would use SharePoint for.  That is, you will have local copies of discussions, meetings, business forms, and more.  When you're back online, everything syncs up so that you get new content, and your new content is pushed to everybody else.

I'm working on a collaborative project right now, and it's a hassle having some things in FolderShare, some things in a SharePoint site, and most discussions in email.  I really see Microsoft Office Groove 2007 as being the solution to this headache starting next year.

tags: , , ,

Millahseconds

Got 6 minutes and 3 seconds with nothing to do?  Why waste your employer's bandwidth and time visiting Hamster Dance when you could instead give that crazy rat bastard named Mark Miller a listen-to on his new podcast, Millahseconds.

In his own words: http://www.doitwith.net/2006/09/12/TheEndOfMyProfe...

 

tags: , ,

Friday, September 01, 2006

When Marketing Plays with Version Numbers

What confusion could possibly arise out of allowing a marketing department establish the framework version number? 

http://forums.microsoft.com/MSDN/ShowPost.aspx?Pos...

The invention of a "vNext" versioning scheme kind of tells me that nobody really knows for sure what's going on with framework version numbers or product release cycles inside of MS.  I mean, ADO.NET 3.0 was supposed to be part of the version 3 .NET Framework (along with LINQ), which is why it had the "3.0" after it.  But, now it seems that there will be a whole set of APIs that will have to skip the 3.0 version number in order to catch up with the framework version when (if) marketing ever decides what the next version number should be.

All of this started as an effort to minimize confusion that they thought would arise from having WinFX be a separate library from the .NET Framework.  Keep it up, guys!  You certainly minimized global confusion with that move.

tags: , ,

Tuesday, August 29, 2006

Hanselman Updates Ultimate Tools List for 2006

Wow, the last 3 posts here, including this one, have been inspired by Scott Hanselman.  I didn't really intend it that way, but it seems that he's the only one posting things that really pique my interest at the moment.

Anyways, the 2006 Ultimate Tools list has been released!  Check it out at:

http://www.hanselman.com/tools

tags: ,

Friday, August 25, 2006

Hanselman's Endianess Converter Challenge

Scott Hanselman asks for the fastest way to flip the bits of a number in order to change the Endianess.  To make it more challenging, he doesn't just want straight conversion of a 64-bit integer to another 64-bit integer.  Instead, he wants to specify the size of the number to reverse (i.e., only the lower x number of bits).

Note: It was brought up that it probably isn't accurate to describe this as an Endianess converter, because Endianess really only affects the individual bytes or words in memory, not the total order of those bytes or words.  That is, if you have a string of memory containing "1234", then converting Endianess would be more akin to resulting in "2143" than "4321".  Scott's challenge is really for the latter example, which is total reversal of the bits.

There were a couple of interesting solutions posted in his comments section.  But, remembering back to the same time period as my previous post, I knew that one of the fastest approaches uses a tradeoff of utilizing memory instead of computation.  That is, you perform some level of pre-computation, and then your function only has to do lookups from an array and simple addition/bit shifting.

Part of the problem is determining how much memory you can afford to use for this task.  I thought that working with 8-bits at a time was a nice starting point, because 8-bits is at the boundary of an intrinsic type (the "byte" type), and because my table (an array) then only needs to be 256 elements in size. 

The contents of this table is the flipped byte for each index value.  The algorithm then is to loop through the original number, grab the lower 8-bits, look up the flipped byte value from the table, and then left-shift it into the output variable.  At the end, right-shift the output variable to make the final number only have the specified number of significant bits.

byte[] flippedBytes = new byte[] {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF};
long Reverse(long x, int bits)
{
long z = 0;


// reverse the bytes
for (int i = 0; i < 8; i++)
{
z = (z << 8) + flippedBytes[x & 0xff];
x = x >> 8;
}
return z >> (64 - bits);
}

For a slight performance increase, get rid of the loop and just "manually" iterate the 8 times (this eliminates a comparison and branch operation).:

long Reverse(long x, int bits)
{
long z = 0;



z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;
z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;
z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;
z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;
z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;
z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;
z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;
z = (z << 8) | flippedBytes[x & 0xff];
x = x >> 8;



return z >> (64 - bits);
}

The execution time can further be cut in half by storing flippedWords ("ushort" types) instead of flippedBytes ("byte" types).  However, this requires 512 times the memory for storage (64K elements * 2 bytes a piece = 128KB instead of 256 bytes).

ushort[] flippedWords = new ushort[1 << 16];



public Class1() // Constructor
{
// Initialize the array
for (int i = 0; i < flippedWords.Length; i++)
{
flippedWords[i] = (ushort)((flippedBytes[i & 0xff] << 8)
| flippedBytes[(i >> 8)]);
}
}
public long Reverse(long x, int bits)
{
long z = 0;



z = (z << 16) | flippedWords[x & 0xffff];
x = x >> 16;
z = (z << 16) | flippedWords[x & 0xffff];
x = x >> 16;
z = (z << 16) | flippedWords[x & 0xffff];
x = x >> 16;
z = (z << 16) | flippedWords[x & 0xffff];
x = x >> 16;



return z >> (64 - bits);
}

And, to put this thing to bed, there's one more little thing that can improve execution time: control the iterations based on the number of bits desired.  That is, if we only need 12 bits in the output, then there's no reason to execute the other 3 iterations.  This method provides better performance only if the bits parameter is less than 48, otherwise the previous method proves faster (because there are no conditions):

public long Reverse(long x, int bits)
{
int iter = (bits >> 4) + 1;



long z = 0;



for (int i = 0; i < iter; i++)
{
z = (z << 16) | flippedWords[x & 0xffff];
x = x >> 16;

}



return z >> 16 - (bits & 0xf);
}

tags: , , , ,

Using Windows to Drive High-Speed Digital Logic

Scott Hanselman is obviously working on another Coding for Fun article.  ;-) 

It looks like he's simply trying to drive a high-powered IR transmitter directly from a Windows application to simulate a Sony remote control. However, he's also running into a challenge that anyone who's tried to use Windows for realtime systems has experienced: there are no guarantees surrounding timeslices in user mode.

I once wrote software that had to do something very similar (this was in an era before .NET). In my case, I was flashing an 8-bit Atmel AVR microcontroller using its SPI bus. The AVR was installed in a device that [I believe] used the RTS flag of RS-232 to both clock and set the SPI data, which was interesting to say the least.

As a background, SPI (Serial Peripheral Interface) is a 3-wire protocol that uses a Master/Slave configuration (in this case, the AVR was always the Slave device).  There's a Master-In-Slave-Out line (MISO), a Master-Out-Slave-In line (MOSI) and a Serial Clock line (SCLK) controlled by the master device.  While SCLK is low, each device is free to change its respective data line state.  The slave reads in the next bit from the MOSI line on the rising edge of SCLK, and the master reads in the next bit from the MISO line on the falling edge of SCLK.  Then the cycle repeats.

The In-Circuit Programming circuitry of this particular device used a Resistor-Capacitor (RC) network and an inverter to both delay and invert the SCLK logic and put the results onto the MOSI line.  So, by carefully timing the transitions of SCLK, I was able to clock in a bit and then prepare for the next bit.

Example: to set the value of 1011, I might have to do:

                  _______          
SCLK/RTS _______| |_______||________|

Which, due to delay and inversion, puts the MOSI line into the following state:
          _________         ___________________
MOSI |_______|
^ ^ ^ ^
Reads 1 0 1 1

The delay that I had to work with was set by a combination of the RC values, the inverter's voltage threshold before it would change state, and the inverter's switching time.  Roughly put, though, it was a really small value represented in microseconds, much like Scott's requirements for the Sony IR Remote protocol.  So, in certain critical areas, I had to make low-high-low SCLK transition that were less than the delay factor, otherwise I would get a wrong value clocked in.


I no longer have the source code to refer to, but I believe that I ended up writing a command-line application in C (no fancy C++ stuff) to call a Win32 API function like Scott is doing.  However, like Scott, I was not getting consistent results, regardless of what priority my process was set to.  The reason that I came up with: the Windows Kernel could at any time steal timeslices from my process when it had something important to do.  My user mode application was always going to be a second class citizen.


Now, one member of this project took my prototype and set off to write a Kernel-mode driver (this was too advanced for me at the time, and probably still is today).  Even with this approach, he still had timing issues every now and then, depending on what was running on the system.


Instead of trying to get Windows to speed up, I took another approach and made the hardware slow down.  By increasing the resistor's value, I was able to increase the delay factor to a point where I could get consistent results from the Windows app.


I wish I still had all of that hardware and source code today.  I would love to see if the same issues exist on modern hardware, as opposed to the PIII-500 with 256MB of RAM running Win98SE.  But, based on what Scott is experiencing, it looks like the issues are still there.


, , , ,

Wednesday, August 23, 2006

Want a Free Trip to TechEd Europe 2006?

Microsoft, via Carl Franklin and .NET Rocks!, is giving away a trip to TechEd: Developers Europe this November in Barcelona, Spain. 

All that you have to do is listen to the podcast, fill out a small survey on the website, and then provide the answer to a question that comes from that week's episode. 

Details can be found at: 

http://www.dotnetrocks.com/barcelona.aspx

tags: , ,

Can You Feel the Tension?

Big oil must be upset this week. 

There are no hurricanes disrupting upstream operations in the Gulf, the ceasefire in Lebanon is [for now] holding, and terrorist plots are being thwarted.  The global outlook is, for the moment, actually positive.

The apparent result: gasoline prices in my area have fallen 12% over the past few weeks.

But, are you like me?  Can you feel the tension?  Can you feel the twisted desire for some bad news to come from somewhere, just so that the local price at the pump can jump 30 cents overnight?

It's the calm before the storm.  Gozer the Gozerian is coming.  Fuel prices will rise again.

 tags: , ,

Tuesday, August 22, 2006

It's All About Averages

If you listened at all to the mainstream media last year, then you would have expected Florida and the Gulf Coast to have been wiped out by now due to a series of severe hurricanes.  I mean, they were preaching that global warming is out of control, and that we can expect our oceans to boil off any day now.

Well, it seems that this year's hurricane season is actually on a less-than-average trend:

http://www.weatherstreet.com/hurricane/2006/hurric...

The Earth has always changed, even before man was around to observe it.  The funny thing about the Earth is that it tends to make its climatic changes over thousands, or hundreds of thousands of years.  The funny thing about mankind is that we tend to form our conclusions based only on a small set of most recent data.  (As a case in point, I've concluded that this will be a mild hurricane season based on the level of activity thusfar).

We're so convinced that major permanent changes are going to happen in our lifetime, that any time there is a winter with major snowfall, or a summer with a drought, or a hurricane season with 26 tropical storms, we're ready to accept that as the new norm.  Fortunately, spikes like these are just noise: the true signal can only be obtained by taking the average over a relatively long period of time (decades or centuries).

Do I think that global warming exists?  Sure, to some degree.  But, I don't believe it to be as serious as some people make it out to be.  And I think that it may have happened regardless of whether or not we were here to witness it.

But, I've already blogged about this topic before... 

tags: , ,

Monday, August 21, 2006

Restoring a SQL Server Backup from Another Server

I'm going to use my blog as a scratchpad for me to remember something that I normally have to Google for each time that I need it.  Feel free to find the following useful, if that thought appeals to you.

Scenario: In order to migrate a database from one server to another (i.e., in order to create a development version on your laptop that will allow you to work offline or offsite), you restore a backup created on the original server, overwriting the database on the destination server (intentionally). 

Problem: If the database uses SQL Server Logins for security, then the logins specified in the backup will not match up with the logins on your destination server (think ID mismatch).

Solution: sp_change_users_login 'AUTO_FIX', 'theUserName'

tags: ,

Friday, August 18, 2006

Number of Week Days in a Date Range Function

I needed a graceful way to count the number of "week days" that existed in a given date range.  At least in the United States, a weekday is between Monday and Friday (i.e., Saturday and Sundays are weekends).

I looked through some of the common BCL objects, and Google'd a bit, but didn't find a pre-written solution (but, the way my afternoon is going, it could have been staring me in the face and I just didn't see it).

Here's a function that I whipped together.  I tried to make it flexible by using the DayOfWeek enumeration (in case another calendar might have a different set of Days of Week, etc) and allowing the definition of a "weekday" to be specified as any day between "wkStart" and "wkEnd" inclusive.

public int WeekDaysInDateRange(DateTime start, DateTime end)
{
int DaysInWeek = Enum.GetValues(typeof(DayOfWeek)).Length;

DayOfWeek wkStart = DayOfWeek.Monday;
DayOfWeek wkEnd = DayOfWeek.Friday;

// Adjust the start date to the first week day, if needed
if (start.DayOfWeek < wkStart)
{
start = start.AddDays((int)(wkStart - start.DayOfWeek));
}
else if (start.DayOfWeek > wkEnd)
{
start = start.AddDays(DaysInWeek - (int)start.DayOfWeek + (int)wkStart);
}

// Adjust the end date to the last week day, if needed
if (end.DayOfWeek > wkEnd)
{
end = end.AddDays((int)(wkEnd - end.DayOfWeek));
}

TimeSpan duration = (end - start).Duration(); // "Absolute value"

int wks = duration.Days / DaysInWeek;
int days = wks * ((int)(wkEnd - wkStart) + 1);

days += ((int)(end.DayOfWeek - start.DayOfWeek) + 1);

return days;
}

Anyone have a more graceful method?


tags: , , ,

Tuesday, August 15, 2006

QuickTimeCheck Scriptable Object

Within the past few days, I've noticed that while browsing a variety of websites, from my Blog, to StatCounter.com, to Scott Hanselman's blog, that an Information Bar was popping up in IE7 stating the following:

This website wants to run the following add-on: 'QuickTimeCheck Scriptable Object' from 'Apple Computer, Inc. (unverified publisher)'. If you trust the website and the add-on and want to allow it to run, click here...

Now, I'm kind of against installing anything that has "Apple" and "Quicktime" in the same sentence, especially since Quicktime has almost become viral in nature (try installing iTunes by itself), so I just have been ignoring the Infobar. 

At first, I thought that maybe StatCounter was at fault.  There's a script that tries to collect capabilities about the clients that access my blog, etc (things like what screen resolution they use, what operating system, what processor, whether JavaScript is supported, etc) and I thought that this was just one more of the data points being examined.

As it turns out, it's the "Don't Be Evil" folks [Google] that are trying to install this ActiveX component as part of the AdSense advertisements that I (and the other sites) have displayed on our sites.

tags: , ,

For Dustin

Here you go, Dustin.  Hang these on your monitor as you write the next CodeRush feature... ;-)

Jason on the bike 003

Jason on the bike 002

tags: ,

Monday, August 14, 2006

Windows Live Writer

Oh, the Blogosphere is alive today with the announcement of the beta release of Windows Live Writer.  This is an offline WYSIWYG blog post editor that was released by Microsoft at a very attractive price: Free.  (This is a beta version, but I assume that the final product will also be free).

Like everyone else, I jumped on the bandwagon to try it out.  In fact, you're looking at my first "TEST POST" (kind of the "Hello World"-type of post that everyone's been polluting my RSS feeds with).

During setup, it asked me for the URL of my blog, and a username/password to access the blogger interface as.  I wasn't really surprised that Blogger.com was one of the supported blogging platforms, but what did surprise me was my first experience of editing a post.

You see, it pulled down my blog template (including embedded stylesheets, etc), and provided a true WYSIWYG experience as I'm editing.  For example, here's a screenshot.  Notice the blog post title at the top replicated in the same style as my blog's website:

 

What's more is that there's a Preview mode that incorporates my full blog template, including other posts:

 

And now the real test of its performance: I'm going to paste some code from Visual Studio into the blog post to see what happens:


double GE = 398600.8; // Earth gravitational constant value
double KM_PER_EARTH_RADII = 6378.135;

double KE = Math.Sqrt(3600.0 * GE /
(KM_PER_EARTH_RADII * KM_PER_EARTH_RADII * KM_PER_EARTH_RADII));

double NO = tle.RevolutionsPerDay * 2 * Math.PI / 1440.0;

double IO = tle.Inclination * Math.PI / 180.0;
double EO = tle.Eccentricity;
double WO = tle.ArgumentPerigee * Math.PI / 180.0;
double OMEGAO = tle.RightAscension * Math.PI / 180.0;
double MO = tle.MeanAnomaly * Math.PI / 180.0;


Hmm, that was anti-climactic.  It just grabbed the plaintext instead of the rich text.  (I had to manually put in the <hr> tags that you see rendered as lines above and below the source code...)  Oh well.

Now for the things that I don't like:

  1. It looks like the only option that I have for publishing images from WLW is to use a FTP server somewhere (since Blogger's image hosting service is kind of an add-on to the main blogging interface).  I don't have FTP access to an image server, so I'll need to add images after the publish.
  2. The "Insert Map" feature uses Windows Live Local (yeah, duh).  However, it also tries to insert a thumbnail image of the map into the blog post, which leads to an error when publishing (see the previous bullet).
  3. Blog posts and drafts are stored locally on your hard drive under My Documents/My Weblog Posts.  However, the .wpost file is binary (i.e., uses a Binary Formatter to serialize the post) and cannot be used/modified outside of the scope of WLW.  I would have like to seen the ability to Save As html, etc.

That's it for now.  I'm sure that it's only time before we see a lot of cool add-ins, like an Upload to Flickr feature that will solve the problem of image publishing.  So far, it seems to be a cool little utility (disclosure: I have not used any other offline editor, like BlogJet, etc, so this is my first experience creating a blog post without using Blogger's web interface).

tags: ,

Friday, August 11, 2006

XmlDataSource: XPath Workaround For Default Namespaces

Having not worked with the XmlDataSource control in ASP.NET 2.0 until this week, I was surprised to learn that there was no way to force it to use namespace-qualified XPath queries, which are critical for querying XML with a default namespace set (either at the root or for some branch of the tree).

PRIMER
XML is a text-based data format that utilizes the concept of tagging data in order to form a tree structure. A simple XML document might look like the following:

<xml>
<Person name='Jason'>
<url>http://jasonf-blog.blogspot.com</url>
</Person>
</xml>
(Listing 1)

XPath is a way of specifying which tagged element, or a collection of elements, that you are interested in. For example, I can query the above XML for the "url" element of the "Person" named "Jason" by using the following:

/xml/Person[@name='Jason']/url

Each slash separates the individual elements that are in the path of the nested data. The square bracket after an element is known as a predicate, and is used to filter the results (i.e., in case there are multiple "Person" elements, this predicate only returns those elements with a "name" attribute containing the value of "Jason").

As XML became more and more popular, developers started merging data obtained from different XML documents into one. This led to tag name conflicts, because one XML document might contain a "Person" tag that has a totally different meaning than another XML document's "Person" tag. The workaround for this situation was to define Namespaces to identify the context of the elements within the XML. Consider the following:

<xml>
<Person name='Jason' xmlns='WebsiteUserNamespace'>
<url>http://jasonf-blog.blogspot.com</url>
</Person>
<Person name='Jason' xmlns='UsergroupLeadersNamespace'>
<url>http://www.nwnug.com</url>
</Person>
</xml>
(Listing 2)

This demonstrates how two nearly identical Person elements can be assigned to different namespaces (implying that they have two different meanings). The first "Person" element (and all of its child elements) belongs to a namespace called "WebsiteUserNamespace", while the second one belongs to "UsergroupLeadersNamespace". Another way to write the same data, but make it a little easier to work with, is as follows:

<xml xmlns:a='WebsiteUserNamespace' xmlns:b='UsergroupLeadersNamespace'>
<a:Person name='Jason'>
<a:url>http://jasonf-blog.blogspot.com</a:url>
</a:Person>
<b:Person name='Jason'>
<b:url>http://www.nwnug.com</b:url>
</b:Person>
</xml>
(Listing 3)

Here, we're actually defining aliases that are used as prefixes for the tag names. In this case, "a" represents the "WebsiteUserNamespace", and "b" represents "UsergroupLeadersNamespace". Notice that the first "Person" element has all of its tags prefixed with "a" while the second "Person" element is prefixed with "b". This is what makes Listing 3 equivalent to Listing 2.

Now, to query for the "url" of the "Person" with a name of "Jason" that belongs to the "UsergroupLeadersNamespace", I would use the following XPath:

/xml/b:Person[@name='Jason']/b:url

The reason why I said that using prefixes is easier to work with has to do with the concept of default namespaces. Notice that the namespace declarations in Listing 2 does not include an alias prefix definition. This makes every unprefixed element from that branch in the tree a member of that namespace. It is common for the entire document to have a default namespace set, meaning that every element within the XML belongs to that namespace.

The problem with unprefixed elements in XML belonging to a namespace is that you cannot construct a XPath query to drill into these elements (because XPath is what requires the prefixes).

The .NET XML parser solves this problem by allowing you to create a XmlNamespaceManager, and defining a prefix at runtime to represent any particular namespace. Then, you can evaluate XPath queries using these custom prefixes that do not exist in the XML document so long as you supply the instance of your XmlNamespaceManager object (i.e., as an optional parameter on a SelectSingleNode(), etc).

Back to the Topic
Now, what I discovered this week was that the XmlDataSource control in ASP.NET allows you to specify a XML document and an XPath to use in order to return a set of nodes (that can then be bound to a TreeView control, etc). But, it did not provide any mechanism to allow the developer to pass in a XmlNamespaceManager. So, if your XML had a default namespace declared, you were pretty much screwed because you could not construct a XPath query.

Searching the internet found these posts:

(I gave up on searching at this point because everything seemed to come to the same conclusion)

The closest thing to a valid workaround was Bill Evjen (pronounced like the bottled water, Evian) suggesting that you just transform the XML first using XSLT in order to remove the default namespace (XSLT transformation is another feature of the XmlDataSource control). Then, you can construct a valid XPath query without worrying about prefixes.

There is an alternative solution that does not require the transform, and allows you to still use namespaces if and when you need to. It's kind of a head-slapper for those who know XPath.

Consider the following XPath:

/xml/*[name()='Person' and namespace-uri()='UsergroupLeadersNamespace' and @name='Jason']/*[name()='url']

It is a little more complicated, yes, but allows you to work with the original XML as-is. Here's the magic of how it works (using Listing 2 as a source of data):

The root "xml" element did not have a default namespace defined, so it can remain in the XPath as is (no prefix). However, the "Person" element belonging to the "UsergroupLeadersNamespace" needs a prefix in XPath. Or does it?

Turns out that if I just use "*" as my second step, then that selects all elements that are children of the root "xml" node. I can then create a predicate that utilizes the built-in XPath functions of "name()" and "namespace-uri()" in order to match these to the values that I need to use.

Finally, because my second step matched the namespace-uri to "UsergroupLeadersNamespace", and I know that in the case of Listing 2, all elements below that point belong to the same namespace, I don't have to continue checking the namespace-uri() value in the predicates of subsequent steps (i.e., I can get away with only checking the name() value).

Bottom line:

/xml/*[name()='Person' and namespace-uri()='UsergroupLeadersNamespace' 
and @name='Jason']/*[name()='url' and namespace-uri()='UsergroupLeadersNamespace']
becomes equivalent to being able to use
/xml/b:Person[@name='Jason']/b:url
if you could pass in a XmlNamespaceManager object.

kick it on DotNetKicks.com

UPDATE 2006-08-14: I just wanted to disclose that after Googling a bit more, I found plenty of references to the XPath method described here for querying namespace-qualified XML (just not in the context of the XmlDataSource). It's still a neat method to keep in mind in case the scenario ever presents itself again.

Monday, August 07, 2006

IE7 for Windows Vista: Protected Mode Annoyance

I like the fact that IE7 for Windows Vista will have a Protected Mode that it will run in by default for any untrusted security zone. This is actually very similar to something that I blogged about last year before installing Vista or even IE7. It just makes sense.

But, something that doesn't make sense to me at the moment is really hurting the WAF of running Vista: it seems that the Protected Mode also affects File Upload capabilities of web sites by limiting what you have access to.

You see, Tina uses the web-based GMail almost exclusively. She also does a lot of work in Microsoft Publisher, and often needs to email files to her friends. These are saved as simple flat files (i.e., TIFF or JPEG).

But, when she is in GMail, and needs to attach a file, the Open File dialog just shows empty directories. That is, unless she goes into Internet Options and turns off Protected Mode.

It very well could be that I just need to change a magic checkbox setting or something. But, there has to be a balance between running in a protected mode sandbox and allowing access to files for email attachment purposes, etc.

Has anyone else beta testing Vista come across this same issue?

CLR processModel memoryLimit

People like Sam and Dustin probably like crawling around the CLR Internals and garbage collection (that is, the sewage system that keeps everything clean and running properly). For me, it's sometimes interesting, but mostly frusterating. I just want things to work without necessarily knowing why they are working.

Enter a case that my friend and co-worker (btw, you need a website/blog, Murph) has been trying to research and resolve for a month or two now.

The client uses Crystal Reports for web-based reporting. Despite my distaste for CR, this actually isn't the problem, and the reports work just fine for what they need to do. The problem is more related to the fact that web-based reporting needs to use a postback when paginating through the report. The reports are based on Datasets, which are retrieved from a web service (for security reasons). Therefore, in order to prevent querying the database every time the user goes to the next page, the Dataset is cached in the Session.

Well, some of these reports have huge amounts of data associated with them. It seems that if too many reports were requested since the last time that the server was bounced, that they would start to get OutOfMemory exceptions. This, in spite of 3.5GB of RAM on the server.

My first thought was to move away from In-Proc session management (i.e., try the SQL Server-based model). That still didn't work. It was as if garbage collection wasn't doing its job.

Murph then started messing with the setting in machine.config. By default, there's a memoryLimit="60" setting, which means that when the memory pressure of the ASP.NET worker process reaches a 60% threshhold, that it will start a new process (i.e., recycle itself, which by definition, gets rid of uncollected garbage and frees up physical memory).

This sounds all well and good. After all, I like when the system has a failsafe mechanism that cleans up after itself. But, in this case, there was 3.5GB of RAM:

3.5GB * 60% = 2.1GB. If memory usage hits 2.1 GB, then the ASP.NET worker process will recycle itself.

Only, it seems that by default, .NET only allows 2GB of memory for its processes. Therefore, before the 2.1GB threshhold was reached, they got the OutOfMemory exception.

The following was invaluable for helping to resolve the problem:

Source: Improving .NET Application Performance and Scalability - Chapter 17

Configure the Memory Limit
The memory threshold for ASP.NET is determined by the memoryLimit attribute on the element in Machine.config. For example:

<processModel ... memoryLimit="60" .../>

This value controls the percentage of physical memory that the process is allowed to consume. If the worker process exceeds this value, the worker process is recycled. The default value shown in the code represents 60 percent of the total physical memory installed in your server.

This setting is critical because it influences the cache scavenging mechanism for ASP.NET and virtual memory paging. For more information, see "Configure the Memory Limit" in Chapter 6, "Improving ASP.NET Performance." The default setting is optimized to minimize paging. If you observe high paging activity (by monitoring the Memory\Pages/sec performance counter) you can increase the default limit, provided that your system has sufficient physical memory.

The recommended approach for tuning is to measure the total memory consumed by the ASP.NET worker process by measuring the Process\Private Bytes (aspnet_wp) performance counter along with paging activity in System Monitor. If the counter indicates that the memory consumption is nearing the default limit set for the process, it might indicate inefficient cleanup in your application. If you have ensured that the memory is efficiently cleaned but you still need to increase the limit, you should do so only if you have sufficient physical memory.

This limit is important to adjust when your server has 4 GB or more of RAM. The 60 percent default memory limit means that the worker process is allocated 2.4 GB of RAM, which is larger than the default virtual address space for a process (2 GB). This disparity increases the likelihood of causing an OutOfMemoryException.

To avoid this situation on an IIS 5 Web server, you should set the limit to the smaller of 800 MB or 60 percent of physical RAM for .NET Framework 1.0.

/3GB Switch
.NET Framework 1.1 supports a virtual space of 3 GB. If you put a /3GB switch in boot.ini, you can safely use 1,800 MB as an upper bound for the memory limit.

You should use the /3GB switch with only the following operating systems:

Microsoft Windows Server™ 2003
Microsoft Windows 2000 Advanced Server
Microsoft Windows 2000 Datacenter Server
Microsoft Windows NT 4.0 Enterprise Server
You should not use the /3GB switch with the following operating systems:

Microsoft Windows 2000 Server
Microsoft Windows NT 4.0 Server
Windows 2000 Server and Windows NT 4.0 Server can only allocate 2 GB to user mode programs. If you use the /3GB switch with Windows 2000 Server or Windows NT 4.0 Server, you have 1 GB for kernel and 2 GB for user mode programs, so you lose 1 GB of address space.

IIS 6
For IIS 6 use the Maximum used memory (in megabytes) setting in the Internet Services Manager on the Recycling page to configure the maximum memory that the worker process is allowed to use. As Figure 17.12 shows, the value is in megabytes and is not a percentage of physical RAM.

Friday, August 04, 2006

Another NWNUG Blogger

I had lunch yesterday with Dustin Campbell from Developer Express, and we talked about the fact that he was perhaps the last technical person in this section of the Milky Way Galaxy to have a blog. Heck, even my mother has a blog.

His boss, Mark Miller, owns a pretty clever domain name: Do It With .NET (doitwith.net). I mentioned to Dustin how funny it would be if "Did It With .NET" was also available. Well, turns out that it was!

Immediately after lunch, Dustin jumped at the opportunity and purchased the domain name. Then he signed up for ASP.NET hosting with Webstrike Solutions, who we use for www.nwnug.com chiefly because the first 12 months of hosting is free. After a few glitches with their server, I was able to install the latest build of DasBlog (1.9.x), and now he's off and running:

http://www.diditwith.net/

Dustin is always working at really low levels in the CLR. I hope that he will start to report little things that he finds, like when Microsoft changes the meaning of certain HRESULT values in their APIs, etc. He had a good idea for a little behind-the-scenes series on LINQ, too, that he could write about.

Wednesday, August 02, 2006

Should Companies Pay More For Legacy Development?

This week, I scoped out a statement of work for some legacy development: enhancements to a Visual Basic 6.0 application.

It sounds really weird to call VB6 a legacy platform. But since ~2000, the whole Microsoft Platform paradaigm has shifted away from COM-based development to managed code (.NET). With that, so did the skillset of the developer community as a whole.

When everyone was regularly doing VB6 development, myself included, it was called a commodity skillset, and therefore, brought in relatively low billrates for consultants (when compared to more cutting edge languages, like Java). This was just classic supply-and-demand economics.

That mindset still exists today in my customers. They think, "VB6 is old and, therefore, it should be very simple to work with." With that, there is also an expectation of low billrates to perform the work. But, is this necessarily true?

There's now a reverse learning curve involved for me to perform this work: I have to unlearn some .NET syntax in order to write VB6 code, and that directly cuts into my productivity. Not to mention that I primarily work in C# now. (But, for disclosure, I still do A LOT of VBScript development since I have to work on classic ASP/ADO web applications for this same customer).

And that brings me to the title question: Should companies expect to pay more for legacy development, even if the legacy system is less than a decade old?

Friday, July 28, 2006

20,000 Hits

I just checked my stats, and realized that I crossed the 20,000 pageload mark earlier today. Sure, people like Scoble, Scott, or Jim Holmes probably get this many hits in any one day, but at least my readership is growing! These website hits are primarily from Google searches.

Just for fun, the stats about that milestone hit:

Date/Time: July 28, 2006 3:20:48 AM

URL: http://jasonf-blog.blogspot.com/2005/01/gb-pvr-plugin-tutorial-released.html

Referrer:

http://www.google.com/search?q=gbpvr plugins&btnG=Search&hs=03L&hl=en&lr=&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial

Client: A Penteledata Inc. - Cable user in Lititz, PA (USA) using Firefox 1.5 on Windows XP and a screen resolution of 1280 x 1024.

(Stats provided by StatCounter)

Thursday, July 20, 2006

Guitar Tabs Are Now Illegal?

So I went to one of my favorite guitar tablature repositories [GuitarTabs.cc] tonight hoping to continue practicing a song that I've been working on, and discovered that the Fair Use nature of the site is currently in dispute. Now, as a background, the majority of these tabs have been created by people who "reverse engineer" songs and then transcribed their results for public consumption. Some tabs have even been on Usenet since the early 1990's (you can use Google Groups to prove that).

The search by Song Title and/or Author still works, but individual tabs have been removed from the site (replaced with a 'Download of this file has been disabled' image).

The note on the homepage reads:

July 17, 2006

To all "Guitar Tab Universe" visitors:

The company which owns this website has been indirectly threatened (via our
ISP) with legal action by the National Music Publishers' Association (NMPA) as
well as the Music Publishers' Association (MPA) on the basis that sharing
tablature constitutes copyright infringement. At what point does describing how
one plays a song on guitar become an issue of copyright infringment? This
website, among other things, helps users teach eachother how they play guitar
parts for many different songs. This is the way music teachers have behaved
since the first music was ever created. The difference here is that the
information is shared by way of a new technology: the Internet.

When you are jamming with a friend and you show him/her the chords for a
song you heard on the radio, is that copyright infringement? What about if you
helped him/her remember the chord progression or riff by writing it down on,
say, a napkin... infringement? If he/she calls you later that night on the phone
or e-mails you and you respond via one of those methods, are you infringing? I
don't know... but I would really like to know. If anyone has information on
this, please email support@guitartabs.cc.

Apparently, the NMPA/MPA believes that the Internet may be on the foul side
of the legality line they would like to draw here. For me, I see no difference.
It's teachers educating students and covered as a 'fair use' of the tablature.
The teachers here don't even get paid nor do the students have to pay this
website to access the lessons.

An attack on this website is really an attack on every one of you who have
told someone (in person, or via the written word, telephone, or e-mail) how you
play a song on guitar. And who, especially among small websites, has the deep
pockets to fight the NMPA/MPA? They use scare tactics while there is, in fact,
no legal precedent on this matter (to the best of our knowledge). If you are
interested in expressing your opinion to the NMPA/MPA, contact them via their
respective websites. Please do not resort to vulgar language or insults.

Millions of people use the Internet to learn guitar, in one form or
another. It appears the NMPA/MPA and their members do not want to support us and
help us further our education. To you visitors from outside the USA or UK, can
you find your favorite artists' "official sheet music" at your local music
store? Even in the United States and United Kingdom, we often can not. The
NMPA/MPA have a choice to make: either they support us as aspiring guitarists,
or they choose to alienate their customer base. To date, not one sheet music
publisher has contacted this website to either inquire as to our activities or
to express interest in any type of dialogue or collaboration whatsoever. All we
deserve is a cold, indirect, impersonal threat without any explanation? They
should embrace new technologies or else become relics of the old economy.

Since I'm now 'worried' about working around tabs at all, I'm in a tough
situation! Luckily, I'm fairly confident that if I alone listen to a song and
then figure out how to play it by ear, I will then be able to enjoy using that
knowledge to practice and improve my guitar playing skills. Is that what is
necessary for everyone to do? Work these things out alone? What a sad situation.

Sincerely,

Rob Balch
Manager of "Guitar Tab Universe"

If you would like to help out and join the effort to fight for our freedom
to tab and share, please check out MuSATO. You can comment on this
statement and/or situation here.

Wednesday, July 19, 2006

New Air Filter Does Wonders

Of everything that I replaced on the motorcycle, I let the air filter go. It's not a part that you can just pick up at the local auto parts store, so it has to be mail ordered, and I just never got around to it. Besides, the one that came with the bike looked clean enough to me!

Well, on Friday, I decided to finally clean the filter (which uses a reusable foam element). As soon as I applied any pressure to the foam with my fingers, it just crumbled! Uh, oh!

That motivated me to order a new one (cheap replacement, nothing fancy), which arrived last night. I oiled it and installed it this morning, and then rode into work.

WOW! What a difference that made. I could instantly tell that the engine sounded different, I got even more horsepower (which there was already more than I was ever used to), and the idle smoothed out. The new filter even fixed a flat spot/stutter in the revs between 2000 and 3500 RPMs! It's like I have a totally different bike, just by installing a $20 part.

Now the only remaining defect is something that developed about 200 miles ago: leaky fork oil seals. I guess I didn't polish up the forks well enough, and the light rust/pitting that was present was enough to roughen the seal. They're leaky now, but due to how involved the repair is, I will likely wait until after the riding season.

Tuesday, July 18, 2006

My IM

I regularly use a half-dozen different email addresses, so it's not obvious to people which ones are tied to some form of instant messaging. Well, do not fret any longer: if you need to IM me (or if you just want me in your contact list), here's what you can try:

Windows Live Messenger (MSN): firstname nospace lastname at hotmail dot com
Yahoo: firstinitial nospace lastname

BTW: With the new Windows Live Messenger client, there's a new XBOX tab that will show your XBox Friends (if you're using the same "passport" for IM that you use for your XBox ID).

Monday, July 17, 2006

Don't Forget Those Domain Accounts

I got a call today stating that one of the reporting servers at my client's location was down (SQL Server 2000 Reporting Services). We haven't touched anything on that machine for a few days, so I was pretty sure that it wasn't anything with the server itself.

When I finally arrived onsite, I opened a web browser to the URL: http://server/reports

The response was simply a generic "Server Application Unavailable" message. Ok, time to troubleshoot.

I first looked at the Application Event Log. There was a message logged, but didn't tell me anything special:

aspnet_wp.exe could not be started. The error code for the failure is 80004005. This error can be caused when the worker process account has insufficient rights to read the .NET Framework files. Please ensure that the .NET Framework is correctly installed and that the ACLs on the installation directory allow access to the configured account.


Ok, so it did tell me that the problem likely involved the worker account. Now, normally, the ASP.NET worker account is the ASPNET user on Windows XP and the NETWORK SERVICE account on Windows 2003. However, just to make sure, I took a peek at the Machine.config file, and discovered that in this case, my client changed the ASP.NET worker account to a domain account instead. It was a good thing that I double checked: there's nothing worse than spinning your wheels trying to fix a problem using the wrong user ID.

Out of curiosity, I also took a peek at the Security Event Log since the client has auditing enabled on all of their servers. I found some failures logged:


Logon Failure:
Reason: Account currently disabled
User Name: someuser
Domain: somedomain
Logon Type: 8
Logon Process: Advapi


Wouldn't you know it: the same domain account that was specified as the ASP.NET worker account (SOMEDOMAIN\SomeUser in this case) was disabled, per this Login Failure event message. Well, that would explain why the ASP.NET process could not start!

In this enterprise, domain accounts are set to automatically disable after a set time period. This is done in order to help prevent an unused account from remaining active, and potentially becoming a security exploit. There is normally a process to renew an account before it becomes inactive, but sometimes, one will slip through the process, as happened this time.

Tuesday, July 11, 2006

Upcoming Book: Windows Developer Power Tools

Jim Holmes just announced the project that he and James Avery have been collaborating on. It's going to be one monster of a boat anchor book (1100 pages) all about tools that Windows Developers can use to make their work easier (think something along the lines of Scott Hanselman's Ultimate Tools list, but with a detailed article about each tool).

Check out Jim's announcement:

http://frazzleddad.blogspot.com/2006/07/announcing-our-book-windows-developer.html

Disclosure: As a Tech Reviewer, I've gotten to see early drafts of the chapters that they have completed.

UPDATE 2006-08-02: I see that Amazon is taking pre-orders. Reserve your copy today! (link below)

Windows Developer Power Tools: Turbocharge Windows Development with More Than 140 Free and Open Source Tools (Paperback)