WELCOME

This blog is where I post about my consulting work with Microsoft Technologies, and other random tidbits that don't fit in my Photo Blog or my Iraq Blog.

Monday, June 23, 2008

SQL 2008 Frustrations

I have been trying to use SQL 2008 for a new project, but I just broke down and decided to go back to SQL 2005 so that I can be productive.

Even after installing Visual Studio 2008 SP1 Beta I still can't get Visual Studio 2008 to play nicely with SQL 2008... Tools like Schema Compare apparently still don't support "SQL 10" according to the error messages, and there still aren't any SQL 2008 specific database project types.

To be clear I haven't had any problems with SQL 2008 itself, just a lack of tools support.

Saturday, June 21, 2008

Minnesota Developers Conference 2008

I'll be speaking on Enitity Framework development at the Minnesota Developers Conference 2008 on September 9, 2008 in Minneapolis.

Check out the website (http://mdc.ilmservice.com/) there are a ton of great speakers! It should be a great event, so register early.

Wednesday, June 18, 2008

Peeking behind the curtain at a Microsoft presentation

With 45 minutes to go before a presentation to 500 developers in Omaha, Microsoft Evangelist Mike Benkovich (right) is writing a new demo from scratch with help from his manager Brian Moore (center).

It's not that he wasn't prepared for a presentation that he's given several times before in other cities, it just that he thought his existing demos were a little "boring".

Nothing like an untested demo in front of a live audience to make things exciting!

Microsoft opening new development center for Expression Suite in Minneapolis

MINNEAPOLIS, MINNESOTA - Microsoft is actively hiring developers to staff a new development team that will be based in the Twin Cities. The group will be working on parts of Microsoft's new Expression Studio tools for creative professionals.

Expression Studio competes directly with products from Adobe, and Doug Olson, and Bob Pappas, the managers for the new Microsoft team are both alumni of Adobe product development teams based in Arden Hills, Minnesota.

Microsoft has an existing sales and consulting office located in Bloomington, Minneapolis, but there isn't space available in that office for the new Expression team, and so they are currently shopping for office space, location TBD.

The open positions are for senior Software Development Engineers and Software Development Engineer Testers working with C# and WPF. This a rare opportunity to work on a cutting edge Microsoft software product, and live in Minneapolis. Interested candidates should visit http://members.microsoft.com/careers/default.mspx.

Bill Gates keynote at the Office Developers Conference 2008

I'm working the "Architects @ Microsoft" booth at the Office Developers Conference in San Jose this week, but my booth doesn't open until 12:30, and so I had time to take some pictures at the Bill Gates keynote before I get to work in the exhibit hall...

I was standing at the back of the hall with one of the convention center security guards, who doesn't now anything about Microsoft, but has probably watched a lot of keynote speeches over the years. About an hour into Bill's presentation he turned to me, and said, "Wow, he really knows his stuff doesn't he."

I theory Bill should be coasting into his upcoming retirement from day to day involvement at Microsoft, but you would never guess it by watching him speak to a thousand developers for an hour and a half here at ODC 2008.

The view from mission control at the back of the hall. The technician on the left is running the teleprompter for the speakers (no most of them don't do it all from memory... but I'm not sure about Bill).

FedEx had a major demo in the keynote showing off a cool new OBA application they've developed to integrate package shipping and tracking into Outlook. At the end of the demo this FedEx delivery guy ran up on stage with a package for Bill.

The box contained a custom Guitar Hero guitar that is going to be auctioned off to some lucky ODC attendee.

Silverlight news: Tafiti source code released and a new Silverlight development site

A couple pieces of great news for Silverlight developers:

1. Microsoft has just released the source code for Tafiti (http://tafiti.com) on CodePlex: http://codeplex.com/WLQuickApps Tafiti is one of the most sophisticated SilverLight applications I'm aware of at this time, and so this should be an interesting body of code for aspiring SilverLight developers to dig through. Note: This Silverlight 1.0 code, NOT Silverlight 2.0 alpha code, and so it is using JavaScript not C#.

2. Microsoft and CMP Media have just launched a new Resource Center for MS Silverlight site for developers (http://www.ddjresources.com/silverlight/) this looks like another great resource.

My new approach to personal email management

I have adopted a new approach to personal email management that I thought was innovative enough that it is worth sharing.

The problem being solved is to try and find more effective ways to manage my inbox, while reducing the number of people and businesses that I give my primary personal email address to. A secondary goal is to track which businesses use my email address to spam me with unwanted third party junk email, and then easily block that email.

So here is the approach: I have a dedicated domain name "scrappydog.com" with just one email user (me). All email to any email address in the scrappydog.com domain lands in my inbox. This allows me to created a separate dedicated email address for every organization I do business with, and I can create a one off random address for any interaction I want.

Here some examples:

  1. wellsfargo@scrappydog.com
  2. americanexpress@scrappydog.com
  3. somegirlimetatthebar@scrappydog.com
  4. criticalworkstuff@scrappydog.com

Then I can create a single inbox rule to route email addressed TO wellsfargo@scrappydog.com straight to the trash after I close my account there, instead of ten different rules for all of the different addresses they send me email FROM based on different marketing campaigns.

Important point to note: What makes this so simple is that I'm routing ALL the email for this domain to a single inbox, and so there is NO SETUP for a new address, I just make them up on the spot. And I can easily create rules to make them go away.

SharePoint Connector for Confluence

Atlassian has just announced a SharePoint Connector for Confluence, their very popular wiki product (Atlassian also makes JIRA the issue tracking system).

Confluence is a Java based product, and SharePoint (MOSS 2007) already has wiki functionality included. So why am I, a Microsoft employee, highlighting this announcement? The wiki functionality in MOSS 2007 is great, but it's limited, and it doesn't meet the needs of all customers. Confluence is a mature popular product which some of my large enterprise customers are currently using. Those customers are also using MOSS 2007 and this product will let them bridge the two together into a single user interface with shared search provided by MOSS 2007.

I think this is a great example of the sort of Software + Services (S+S) integration that we are working to highlight with core parts of the Microsoft stack acting as the glue to tie enterprise applications from a variety of vendors together for improved user experience.

Here is a link to product information on the Atlassian site: http://www.atlassian.com/sharepoint/default.jsp

Meeting with a startup

I had an interesting meeting with a new startup this morning. I can't tell you their name, or much about them, but I there are still some interesting bits worth sharing.

This is a very early stage company that just secured $3+ million in VC money. Up until last week they were primarily funded by the three founders credit cards. They are doing business in the financial services space, and while they aren't going to be dependent on the web for their revenue, they do see the web as a key differentiator and value add to their business model. I was asked to come in and give them a briefing on the Microsoft platform and how it fits with their plans.

We had an interesting discussion of the process of selecting a technology platform in a green fields opportunity like this. A key point that I made was that in a situation like this where a startup company is planning to develop a large custom application from the scratch the most important consideration isn't necessarily the licensing cost or capabilities of the platform nearly as much as the availability of talent to actually do the work.

Here in Minneapolis-St Paul the market isn't really a very active LAMP (open source) market in terms of use by big business or in terms consulting resources. So my point was that they could choose "free" tools in the LAMP space, but they might have a difficult time staffing up to do the work. By contrast there is a lot of .NET (and Java) development going on here in the Twin Cities, and the pool of talent is much larger.

There are obviously lots of factors that go into a "bet the business" decision on a technology platform, but being able to staff up your startup is certainly a key one.

From a technology capabilities perspective BizTalk and SharePoint are a great fit for this business, and as they move forward I'm hoping to follow their story, and report on their progress. Stay tuned...

Subtle MSBuild bug (feature)

I've got a fairly complex MSBuild script that has a subtle problem that has taken me a while to diagnose. The symptoms where basically that the first "fixed" build would often fail. What I mean by this is that after a compile problem was fixed the next build would fail to create an *.msi file because it said there were missing files. Here is an outline of my build process:

  1. Get the latest code from Source (Un)Safe.

  2. Clean (delete all bin and obj directories).

  3. Compile 65 VB.NET 2005 projects individually in dependency order (NOT using a master solution file).

  4. Copy most of the build output to a common bin directory.

  5. Run an InstallShield script that packages the files in the common bin directory into an *msi file.

  6. Copy the resulting *.msi file to a turnover directory.

  7. Email QA to let them know there is a new build available.

Here is a simplified version of the MSBuild script for step 4:


<Target Name="CompileWithStop">



<MSBuild



Projects="@(ProjectReferences)"



Targets="Build"



StopOnFirstFailure="True" />



</Target>





<ItemGroup>



<CompileOutput Include="..\Source\**\bin\**\*.exe" Exclude="..\Source\**\bin\**\*.vshost.exe" />



</ItemGroup>





<Target Name="Copy" >


<Copy SourceFiles="@(CompileOutput)"

DestinationFolder="$(OutputDirectory)"></Copy>



</Target>



And here is the bug: It turns out that all ItemGroups in an MSBuild script are processed BEFORE all Targets! So this means that my CompileOutput item actually is based on the files that were generated by the PREVIOUS build! The insidiously subtle part of this is that builds usually generate the same output, so the script "works" except for the first time new file is added, or the first time after a broken build that didn't generate all of it's output files.

Fortunately there is a solution. The CreateItem task can be used to create an Item within a Target. The MSBuild snippet below fixed my problem:



<Target Name="Copy" >



<CreateItem Include="..\Source\**\bin\**\*.exe" Exclude="..\Source\**\bin\**\*.vshost.exe">



<Output TaskParameter="Include" ItemName="CompileOutput" />



</CreateItem>





<Copy SourceFiles="@(CompileOutput)"



DestinationFolder="$(OutputDirectory)"></Copy>



</Target>



This "feature" is apparently "by design", but it is definitely counter intuitive. I had incorrectly assumed that an ItemGroup was processed when (and only IF) it was referenced...

Here is the reference that solved it for me: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=390321&SiteID=1

Determining your Terminal Server Session ID from C#

I ran into an interesting .NET Remoting problem yesterday: Users on Terminal Services were stomping on each other running an app with a "private" remoting server that hadn't taken into account the possibility that multiple user could be trying to run it simultaneously on the same computer.

So the next question became: How do we uniquely identify separate instances on the same server? The quick answer was username, but that would fail if a user had multiple terminal server sessions. The better answer was to use the terminal server session id. Here's a code sample to determine your session id:

[DllImport("kernel32.dll")]

static extern bool ProcessIdToSessionId(uint dwProcessId, out uint pSessionId);

static void Main(string[] args)

{

Process _currentProcess = Process.GetCurrentProcess();

uint _processID = (uint)_currentProcess.Id;

uint _sessionID;

bool _result = ProcessIdToSessionId(_processID, out _sessionID);

Console.WriteLine("ProcessIdToSessionId Result: " + _result.ToString());

Console.WriteLine("Process ID = " + _processID.ToString());

Console.WriteLine("Session ID = " + _sessionID.ToString());

Console.ReadLine();

}



Notes:
  1. On a standalone workstation the session id is zero (0).
  2. The console session on a server is also zero (0).

Outlook - Gmail emoticon wierdness

I've been getting some emails lately at my personal Gmail account from people at Microsoft with a freestanding "J" or "L" at the end of some sentences... emoticon like syntax and placement, but more cryptic... I thought I had missed the memo on some new internet meme or shorthand, but it turns out it's just a "feature" of how Outlook translates some standard emoticons into images.

Here is a test message in Outlook.


And here is how the message was received in Gmail.


Proving yet again that Microsoft and Google just don't want to talk to each other... :-) (or should I say J)

VB6 to VB.NET 2005 migration wizard issue: Untranslated statement

Here is the evil VB6 to VB.NET 2005 migration issue of the day:

The migration wizard generates about a zillion 'UPGRADE_xxxx comments in the the migrated .NET code, and many of the them are pretty trivial. On our current project we've gotten a little complacent about most of the ones that aren't "'UPGRADE_ERROR:", some of the "'UPGRADE_WARNING:" messages are actually critical code breakers too.

I just discovered that we have a few of these sprinkled through our code:
'UPGRADE_WARNING: Untranslated statement in . Please check source code.
This means that the Migration Wizard LEFT OUT some code it didn't understand, and you need to go back to the VB6 source, and copy and paste it into .NET!

Fortunately this doesn't happen very often (16 occurances in 956,000 lines for us), but it leads to some ugly bugs if you don't search for all occurances of the warning message and fix them.

VB6 migration show stopper of the day: Ocx's with runtime licensing

Apparently the VB.NET 2005 Migration Wizard doesn't know how to migrate runtime licensing keys for Ocx controls.

Steps to reproduce:
  1. Create a one page hello world app in VB6, and add an Ocx that requires a runtime license.
  2. Migrate the app to VB.NET 2005, and compile it on a workstation with the appropriate design time license installed (I've tested this with several older Farpoint controls).
  3. Run the .NET app on the developer workstation that built it. It runs fine.
  4. Copy the compiled application to a test workstation that does not have the design time license installed, and try to run it. It fails with a license not found error.
Work arounds (both very painful):
  1. Delete each offending control in a .NET form, and then re-add it (by drag and dropping it on the form in the designer). This will cause the runtime license to be created, but you need to rename, resize and reconfigure the control. Repeat this process several thousand times...
  2. You can also copy known good OcxState data from another form with the same type of control into the *.resx files for the .NET forms. The advantage of this approach is that you don't have to rename and reposition the control on the form, but you still have to manually restore other formating and configuration properties.
Bottom-line: This is a huge PITA. I really hope that there is another fix that we haven't discovered yet.

VB6 Migration: Non-zero based arrays

VB6 allows you to define arrays that are non-zero based, for example:

Dim RecentPolicies(1 to 4) as String

In .NET all arrays are zero based and the migration wizard generates the following code:

'UPGRADE_WARNING: Lower bound of array RecentPolicies was changed from 1 to 0. Click for more: 'ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?keyword="0F1C9BE1-AF9D-476E-83B1-17D43BECFF20"'

Public RecentPolicies(4) As String

This is frankly evil, the migration wizard does NOT fix any of the related code, and so have go fix are you code. For example:

RecentPolicies(intI) would need to be changed to: RecentPolicies(intI - 1)

But I was thrilled to discover yesterday that Francesco Balena has come up with a really slick solution to this problem, which is essentially a new type that supports non-zero based arrays! So instead of the ickyness described above you can simply change your VB.NET 2.0 code to:

Dim RecentPolicies As New VBArray(Of String )(1, 4)

This is incredible time savings! To get the code read Francesco's original blog post here: http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,08e740fc-f486-4b5b-8796-6aad43e08815.aspx

Caveat: This is a Visual Basic 2005 specific solution (due to the use of generics).

Being inherintly sceptical of new things, I wrote the following set of NUnit tests to prove that his code works:

Imports NUnit.Framework

_

Public Class VBArrayTests

_

Public Sub TestLowerBound()

Dim _array As New VBArray(Of Short)(1, 3)

Assert.AreEqual(1, LBound(_array), "Lower bound should equal 1")

End Sub

_

Public Sub TestUpperBound()

Dim _array As New VBArray(Of Short)(1, 3)

Assert.AreEqual(3, UBound(_array), "Upper bound should equal 3")

End Sub

_

Public Sub TestZeroIndex()

Dim _array As New VBArray(Of Short)(1, 3)

Try

_array(0) = 55

Catch ex As System.IndexOutOfRangeException

Assert.IsTrue(True, "System.IndexOutOfRangeException exception was thrown on zero index")

End Try

End Sub

_

Public Sub TestMaxIndex()

Dim _array As New VBArray(Of Short)(1, 3)

Try

_array(4) = 55

Catch ex As System.IndexOutOfRangeException

Assert.IsTrue(True, "System.IndexOutOfRangeException exception was thrown on index of 4")

End Try

End Sub

End Class

Enabling IIS 6 Metabase Compatibility in IIS 7

IIS7 has done away with the metabase, but some pre-IIS 7 applications (such as Virtual Server R2 SP1) rely on the metabase as part of their installation process. This is a Windows feature that you can turn on and off throught the control panel (it is not a seperate install).

Running Virtual Server R2 SP1 on Vista

I've always preferred using Virtual Server to Virtual PC, and today I was setting up Virtual Server R2 SP1 on a new Vista machine, and I thought it was worth noting a couple of issues:

1. The Virtual Server Administration Website is a CGI application, but CGI applications are not enabled by default in IIS 7 on Vista. To enable CGI you need to go to:

> Control Panel

> Programs and Features

> Turn Windows features on or off

> Internet Information Services

> World Wide Web Services

> Application Development Features and check the CGI box.

2. When you try to browse to the Virtual Server Administration Website for the first time you will probably get the following error:

"The following error occurred:
An error occurred accessing the website application data folder."

The solution is that you need to open Internet Explorer as an Administrator (right-click on the IE icon and select "Run as administrator").

3. Installing the Microsoft Loopback Adapter on Windows Vista:

> Control Panel

> Add Hardware

> Click Next on the “Welcome to Add Hardware Wizard”

> Click the “Install the hardware that I manually select from a list” button, and then click Next

> Choose Network adapters click Next

> Under Manufacturer choose Microsoft

> Under Network Adapter choose Microsoft Loopback Adapter.

> Click Next

> Click Next

(The point of installing the Microsoft Loopback Adapter is to allow you to connect the host PC to the Virtual Server "Internal Network" without exposing the guest operating systems on a "real" network.)