Navigation

Search

Categories

On this page

Deleting Multiple Builds from Team Foundation Server
Microsoft Releases .NET Framework Source Code
Generics Based .NET Remoting Event Shim
SMTP Event Sink Registration Problem
Integrating Windows Workflow Foundation and Windows Communication Foundation
Convert.ChangeType() to the rescue of a generic method (and my sanity)...
Hosting Windows Workflow Foundation in Windows Services
The Server Side of the .NET Framework 3.0 Presentation Materials

Archive

Blogroll

Disclaimer
None - these are my opinions and they're also my employer's!

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 14
This Year: 0
This Month: 0
This Week: 0
Comments: 15

Sign In

 Monday, November 05, 2007
Monday, November 05, 2007 9:25:01 PM (Mountain Standard Time, UTC-07:00) ( )

I've been working a lot with Team Foundation Server lately (2005, unfortunately) doing builds and have created a bunch of test builds out on my client's TFS.  I knew the easiest way to delete builds was using the TFSBuild.exe utility but I couldn't find any help on how to send multiple build numbers to the utility on the command line.  I saw a couple of references that said to separate them with commas but that didn't work - it appeared to interpret the concatenated list as one build number.

So, I tried using spaces between each build number and that worked.  Hopefully, this will help anyone else trying to clean up their build messes.  I have a feeling things would have been quite a bit easier had I worked in TFS 2008 but my client couldn't wait until they brought that upgrade into their environment.

Example below: (be sure to use quotes if build names contain spaces)

C:\>tfsbuild delete http://tfsserverurl:8080 "Team Project Name" Development_RC1.3.4 Development_RC1.3.5 Development_RC1.3.6 Development_RC1.3.7 /noprompt

Microsoft (R) TfsBuild Version 8.0.0.0
for Microsoft (R) Visual Studio 2005 Team System
(C) Copyright 2006 Microsoft Corporation. All rights reserved.

Deleting Development_RC1.3.4... Done

Deleting Development_RC1.3.5... Done

Deleting Development_RC1.3.6... Done

Deleting Development_RC1.3.7... Done

Comments [1] | | # 
 Sunday, October 07, 2007
Sunday, October 07, 2007 8:57:56 PM (Mountain Daylight Time, UTC-06:00) ( )

I can't even begin to count the number of times I've been tracing a problem with some set of code and realized there was a problem with my understanding of what the .NET Framework Base Class Library was doing and why. 

Now we'll be able to find out.  Scott Guthrie just announced a new capability with Visual Studio 2008 and .NET 3.5 for retrieving source for many of the framework assemblies.

This is huge.  I can't wait to be able to drill into some of the framework without needing to use Reflector outside the debug bubble.

Comments [0] | | # 
 Saturday, April 21, 2007
Saturday, April 21, 2007 9:10:14 PM (Mountain Daylight Time, UTC-06:00) ( )
I built a Windows service to host different processors that work with MSMQ. Each processor is running in its own AppDomain and needs to fire events to the host service. .NET remoting is used to wire up the connections between the host process and the processors as a result of the cross appdomain communication requirement.
 
Handling events in this scenario requires a handler or shim to be used to avoid requiring a reference to the event subscriber in the event publisher. The shim is simply a broker or proxy for both sides. I tried to find an example of one that used generics but was unable to so I decided to come up with one. It's essentially wrapping the built-in generic EventHandler<T>. This allows any event argument type to be passed as T.
 
Here's the code:
 
   [Serializable]
   public class RemoteEventShim<T> : MarshalByRefObject where T : EventArgs, new()
   {
      public override object InitializeLifetimeService()
      {
         return null;
      }
 
      public event EventHandler<T> RemoteEvent;
 
      public void RemoteEventHandler(object sender, T e)
      {
         EventHandler<T> handler = RemoteEvent;
         if (handler != null)
         {
            handler(sender, e);
         }
      }
   }
Comments [0] | | # 
 Tuesday, April 10, 2007
Tuesday, April 10, 2007 7:31:52 AM (Mountain Daylight Time, UTC-06:00) ( )

I seemed to have hit a quirk in the registration of event sinks in the SMTP service.  As I discussed in this previous post, I had a need to create a managed SMTP event sink and worked out all the kinks in using that to send to a local MSMQ.  Everything has been running great.

However, I needed to install a new version in a side-by-side mode and couldn't for the life of me get the second assembly to load after registering it with the smtpreg.vbs utility.  I tried everything I could think of but nothing seemed to work.  In order to even register I had to create the new version with a different class name so the ProgID would be unique.  I also had to change the ComVisible attribute Guid property so that I would have a new ClassID.  All of this was pretty obvious.  But even after making sure things looked fine in the registry and the IIS metabase (the actual SMTP sinks are all located in the metabase,) I couldn't get my event sink to fire.  I was even registering using a unique name for the registration entry by appending a 2 to the name (e.g. SMTP2MSMQ2 vs. SMTP2MSMQ.)

I had just about given up when I thought I would try prefixing the version to the registration name vs. appending it.  It worked!  I haven't spent any more time (I had already spent way too much time on this) to figure out what the heck was going on but left it up to some weird registration matchup logic due to the name beginning with the same letters.  You can register the same SinkClass multiple times to manage different patterns of email addresses, etc. but apparently the same name with different SinkClasses is a no-no.

Comments [2] | | # 
 Tuesday, February 27, 2007
Wednesday, February 28, 2007 4:44:52 AM (Mountain Standard Time, UTC-07:00) ( )

There is a very interesting article out from Microsoft all about hosting the Workflow runtime behind a Windows Communication Foundation service layer.  There are some great points on using duplex channels so events from the runtime can be sent back to the client.  The design is fundamentally similar to what I've been working on for a few clients as described in this post.

It appears that this is an evolution of the Expense Reporting Sample that's been out awhile.  The first version used .NET Remoting instead of WCF.  Guess they didn't want to use someone else's alpha code to build their beta code :-)

Check it out.

Comments [1] | | # 
 Tuesday, December 05, 2006
Wednesday, December 06, 2006 3:31:37 AM (Mountain Standard Time, UTC-07:00) ( )

Ever had one of those moments when you wished you either knew everything there was to know about software development or had decided to become a pea farmer in Brazil (not that they even have pea farms in Brazil, but they might, but....) instead of a software developer.  Well, I have and a show of hands in a crowded technical gathering would prove my point.  This self-realization should give the reader enough pause about reading on without me clearly stating that I'm sure someone else has solved this problem in a much more elegant way - after all, I'm not even sure they farm peas in Brazil.

Anyway, just when I had decided that I should've given myself more time when I made that fateful "farming vs. programming" decision, along comes an Intellisense moment which made it all better.  I knew about the Convert class and had used it numerous times so I did the fateful "conv+tab+." and started looking for gold.  Sure enough I found it in the ChangeType() method.

The problem...

A fellow developer had written a handy generic method for the type friendly retrieval of application configuration settings.  Everything was working well until I tempted Fate and asked for a value type, int in this case, back from the method:

Error 1 The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'ConsoleApplication1.Program.GetSetting<T>(string)'

Well, that seemed like an important capability to have so diving into the wrapper I went:

public static T GetSetting<T>(string key) where T : class
{
   return ConfigurationManager.AppSettings[key] as T;
}

To start with there was no way to call this method passing int as the generic type because of the class constraint.  So, I quickly modified it to the following:

public static T GetSetting<T>(string key)
{
   return ConfigurationManager.AppSettings[key] as T;
}

Which, of course, just means I'm a lazy programmer (which, of course, translates to reduced crops of peas if I had chosen that profession.)  At first glance, I thought removing the class constraint would be the answer.  Since we don't have to think things out all the time in this age of change/compile/test/change/compile/test/scream/change/compile/test development I let the compiler tell me if my guess was wrong (isn't that the whole point of generics anyway?) kind of like a game of "Who Wants to Be a Millionaire?" without the lifelines:

Error 1 The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint

This error message was so useful since I had just purposefully removed the class constraint.  The super-fast-non-thinking-programmer in me changed it to:

public static T GetSetting<T>(string key)
{
   return (T)ConfigurationManager.AppSettings[key];
}

The very brief moment of insight which caused me to change the cool and friendly as cast to the traditional brute force cast proved NOT to be insightful at all as the trusty compiler let me know: 

Error 1 Cannot convert type 'string' to 'T'

And I thought you could cast pretty easily in the .NET Framework.  Well, you can, but the compiler has no idea what T is going to be so it stops you from making a bad cast and getting a runtime error which of course is apparent evil.  Strong-typing vs. dynamic-typing aside, we were in a real pickle.  We needed this generic method to deal well with a variety of types so...

The solution...(well, you read the title, right?)

public static T GetSetting<T>(string key)
{
   return (T)Convert.ChangeType(ConfigurationManager.AppSettings[key], typeof(T));
}

I am InvincibleChangeType() has several overloads but the one I was interested in took two parameters: 1) object value and 2) Type.  This was exactly what was needed and I had another moment of "I am invincible" and was sure that I had chosen the right pill (talk about mixing movie metaphors.)

The catch...

Everything compiled and my unit tests proved it to be working swimmingly so what was that gnawing concern growing in the pit of my "been around the bend a few times" stomach.  Things seemed happy and well adjusted.  That's about the time I always have hair stand up on the back of my neck.  What's the catch?  Performance?  Odd inconsistencies that will absolutely drive me nuts later?  Deprecation in the next release of the framework?

Armed with nothing but paranoia, I decided to research this little bad boy and see just how awful it was.  Come to find out my worries weren't too justified as I found out while Reflectoring the method in mscorlib.dll.  They actually did what my cohort and I thought we were going to have to do in examining the incoming T parameter's type and finding the right translation from the string results of the ConfigurationManager.AppSettings[key].  So maybe I'm not as crazy as I thought since the framework folks did just what I had planned. 

However, one thing jumped out when I looked closely at the disassembly:

IConvertible convertible1 = value as IConvertible;
if (convertible1 == null)
{
   if (value.GetType() != conversionType)
   {
      throw new InvalidCastException(Environment.GetResourceString("InvalidCast_IConvertible"));
   }
   return value;
}

As I pondered the deeper meaning of what I had just found I realized that it might be a bad thing if I passed in a type parameter for T which was not of the IConvertible ilk.  Which led me to the final version below:

public static T GetSetting<T>(string key) where T : IConvertible
{
   return (T)Convert.ChangeType(ConfigurationManager.AppSettings[key], typeof(T));
}

With the IConvertible constraint on the T parameter I could rest easy that this method should provide years of use without any harmful side effects and that I could lay to rest the ongoing controversy in my mind of peas or C# (yeah, right.)

Comments [3] | | # 
 Thursday, November 30, 2006
Friday, December 01, 2006 6:02:21 AM (Mountain Standard Time, UTC-07:00) ( )

I've been spending some time working with hosting the WF runtime in a WCF-wrapped Windows service.  The idea is to allow these services to be run on servers behind a load balancing technology like NLBS.  In my research I ran across a few great articles and samples which might be useful so I thought I'd post them here.

My goal for these hosting services is to make them as loosely-coupled as possible.  Ultimately, I'd like to have the full set of runtime and service events available through a publish/subscribe architecture similar to Juval Lowy's so that the disconnected and potentially remote consumers could be notified of status and process changes in their respective workflows.  Also, to accomplish the loose coupling, I am taking bits and pieces from the Workflow Adapter/Connector and WS-Transfer Service for Workflow articles that Roman Kiss posted on CodeProject.com.  There's a lot of work to do but I think in the end the architecture is a sound one.  I'm not sure I'll go all the way to WS-Transfer yet but it's definitely a compelling protocol.

There's a good example of hosting workflows in a Windows service out on the Workflow community site.  It also demonstrates the use of IExtension in WCF for hosting the Workflow runtime.

Comments [1] | | # 
 Wednesday, November 29, 2006
Thursday, November 30, 2006 12:22:50 AM (Mountain Standard Time, UTC-07:00) ( )

Just wanted a common place I could reference this presentation and code samples.  It was a fun side project that Matt Brown and I have enjoyed presenting to the local user group and a couple of code camps here in Colorado.  It was originally done pre-Beta 2 so there are definitely things we would do differently now but it does show some cool WCF and WF concepts.  And, it might help in your next job search.

Enjoy.

Comments [1] | | #