Saturday, June 30, 2007

Well, I must say that I'm happy about our very first .NET User Group Lunch which took place a couple of days ago (06/28/2007).  We had about 15 people show up to Ruby Tuesday in Jordan Landing and we had a great time.  I really enjoy the commaradie of the group.  We're going to shoot for another lunch in a few weeks and we're looking for suggestions for locations (both to maximize accessibility and therefore attendance to these events).

If you have thoughts, please follow up on the User Group forums.

Saturday, June 30, 2007 4:19:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Monday, June 25, 2007

This week we're starting what we hope will be a long and fun tradition for the Utah .NET User Group: A .NET User Group Luncheon.

Here are the details as outlined on the website:

By popular demand, we're starting up what we hope will be the first of many .NET User Group lunches.  This is a time where the members of the group can gather, collaborate collectively, frolic and fraternize, and consume comestibles.  We've had a great time gathering after the monthly meetings each month and would like to continue that tradition during the daylight hours when (hopefully) more people can make it..

As a tentative schedule, we're thinking of having a lunch gathering every two weeks at different points throughout the valley.  That way, if you can't make one lunch, hopefully you can make the next one.

This first one will be in Jordan Landing at Ruby Tuesday.  To accomodate everyone's disparate work hours and various commutes, we're allotting 1.5 hrs for lunch from 11:30 AM - 1:00 PM.  You don't need to come for the entire time, show up whenever you like.  Again, things may and probably will change as we get this underway (such as times, dates, and locations), but we just want to get the ball rolling.

We love this group and hope to have a good turnout to this, the inaugural lunch.

If you plan on attending, please check the appropriate option below so we can arrive in time enough to warn them :)

Come one and all, good times are to be had!

Date: Thursday, June 28th, 2007
Time: 11:30 AM - 1:00 PM
Place: Ruby Tuesday in Jordan Landing (
http://www.rubytuesday.com/locator.asp?template=map_search&pWidth=339&pHeight=299&transaction=locMap&recordId=7132)

If you'd like to attend, please visit the post and sign up on the poll, indicating you'll be there.

It should be a lot of fun!

Monday, June 25, 2007 2:47:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Wednesday, June 20, 2007

Tonight I had the distinct pleasure of giving a presentation at the Utah County .NET User Group on the topic of Silverlight - specifically Silverlight 1.1 Alpha.  It was a blast!  Honestly, I was a little nervous going into it, having never really presented on the topic and being relatively new to it myself, but I had a great time.  We talked about Silverlight (previously known as WPF/E) and used Visual Studio “Orcas” with Expression Blend and did some really cool things.  We talked about XAML, created custom controls, retrieved a file from the server and read its contents, automated the HTML DOM from the Silverlight .NET code, did the reverse (called .NET methods from JavaScript), and much more!

If you missed it, never you fear because I'll be addressing the topic at the September 2007 Utah .NET User Group meeting.

Thanks all for coming and to Scott Golightly for giving me this opportunity to present.

Wednesday, June 20, 2007 3:39:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Wednesday, June 13, 2007

Well, the time has once again arrived, my friends, for our monthly Utah .NET User Group meeting.

We will be pleased to have Craig Campbell stepping up to the plate to discuss Team Foundation Server (TFS).  We know that this has been a topic long desired and we're excited to be able to bring it to you.

Topics of discussion will include (but are not limited to):

  • What is TFS (in relation to SCM)?
  • Source Control
    • Comparisons
    • Features
    • Branching/Merging/Shelving
    • Visual Studio Integration/Other integration/Command line
  • Build
    • Team Build
    • Continuous Integration
    • Orcas changes (v2 of TFS)
  • Project Features
    • Work items
    • Methodologies offered
    • Source control integration
  • Customizations/Extensibility

So bring your friends, family, fellows, and fraternities...you won't want to miss this event.  And though there is no need to mention this, I will:  don't forget it's FREE and open to all.

Date: Thursday, June 14th, 2007
Time: 6:00 PM
Place: Digital Draw Network - Suite 300 (10897 South River Front Parkway, South Jordan)

We'll see you there!

Wednesday, June 13, 2007 4:23:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, June 12, 2007

Recently I had the need to create a component in .NET that would be callable as a COM component (not unlike many other such objects in the past).  This one, however, was peculiar in that I also needed to be able to call it from a web page running in IE (due to constraints already on the application, cross-browser support is not a concern in this case).  I didn't want the users to be burdened with dialog boxes or even require that they change their security settings.  I wanted to create the object as 'safe for scripting'.

There are two approaches that I know of that address the issue: implementing IObjectSafety (a COM interface) or directly managing the object via the Component Category Manager (ICatRegister COM interface) and registering the CAT_SafeForScripting GUID.

The first presumes that I have access to and can compile the code, because the IObjectSafety interface must be implemented directly on the object in question.  The second solution can be done after the fact (e.g., within an installer).

Due to the nature of the project, I opted for the first option because, frankly, it was the easier of the two to implement given my time constraints.

The IObjectSafety interface is not native to the .NET world.  As such, in order to implement a COM interface on a .NET object the interface must be defined within the managed code and then decorated with the appropriate attributes.

Here's my implementation of the IObjectSafety interface in managed code:

[ComImport()]
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IObjectSafety {
   [PreserveSig()]
   int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions);
                    
   [PreserveSig()]
   int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions);
}

The ComImportAttribute identifies that the interface was previously defined in COM with the IID specified by the GuidAttribute.  The PreserveSigAttribute is important on each of the methods to tell the .NET runtime to not suppress the HRESULT when the method is called.

Once defined, it's then a simple matter to implement the interface on my class, and indicate that it's safe for scripting:

[ClassInterface(ClassInterfaceType.AutoDispatch)]
[Guid("43B6ADAA-6DE7-43c2-9206-3389C94B9531")]
[ProgId("DemoLib.DemoObject")]
public sealed class DemoObject : IObjectSafety {
   private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
   private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
   private const int S_OK = 0;

   public int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions) {
      pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
      pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
      return S_OK;
   }

   public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) {
      return S_OK;
   }
}

Once registered (via Regasm.exe), you can invoke methods on an instance of the object via your script:

var obj = new ActiveXObject("DemoLib.DemoObject");
obj.CallSomeMethod();

Tuesday, June 12, 2007 11:06:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Thursday, June 07, 2007

I hate little hacks like this, but here it is nonetheless.  If someone has a better solution I would love to hear it.

I've been tinkering with the WinForms TreeView control a bit and ran into a documented (but undesirable) behavior.  I'm wanting to display my hierarchical node structure in the tree, but I want to 'highlight' some of them for one reason or another.  My preferred highlight in this case is to use a bolding effect on the font and to change the text color.

The undesired effect, however, is when you apply a font to the node that is larger than the base font of the node the text will clip.  Well, bolded text is larger - it's wider than the text and as a result the right-most character(s) get clipped and it looks really tacky.

My hack isn't without it's limitations and considerations, but all I need to do to 'workaround' this issue is to apply some non-breaking spaces in the text to display such that they get clipped and not the actual text.  This is definitely error-prone as well because just one nbsp doesn't necessarily address the issue (but does in my situation for most texts).

string text = “This is ridiculous” + (char)160;
TreeNode node = new TreeNode(text);

I can see this being quite an issue with non-latin-based fonts, though I've nothing to substantiate that claim.

One side-effect of doing this is that the 'clip box' around the text grows to accommodate the non-breaking spaces.  You can surely set your TreeView to use .FullRowSelect, and to turn off .ShowLines, but that may not be desirable in some situations.

Does anyone have/know of a better solution with the plain, vanilla TreeView?  I've tried other tactics but none led to any better results.  Maybe I'm missing something blatently obvious.

Thursday, June 07, 2007 7:29:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Wednesday, May 30, 2007

Just the other day I posted some code wherein an MSMQ queue is created and the Network Service account was granted full control to the queue.  Though I didn't mention it, this was necessary because the Windows Service runs under that account and would need access to the queue.

As it turns out the code sample has issues when running on Windows XP.  Windows XP doesn't allow the NT AUTHORITY\NETWORK SERVICE account to be associated with the permissions on a message queue (I've not looked into why yet).  When the code runs no error is thrown and it happily attempts to grant the permissions.  This results in a queue whose permissions are corrupted (not even an administrator can access it) and all users are denied access.  The only way I've found to remove such a queue is to uninstall MSMQ and reinstall it.  Does anyone know of another solution to that?

Therefore, in my code a put a rudimentary workaround to the problem.  I perform a simple check to see if the OS is Windows XP and if so, not set permissions.  This works in this case (though I hate to rely on these behaviours) because the default permissions on a queue in XP is Everyone:Full Control, so the service can see the queue just fine.

if ( !isWindowsXP() ) {
   const string accountName = @"NT AUTHORITY\NETWORK SERVICE";
   Trustee trustee = new Trustee(accountName, null, TrusteeType.User);
   MessageQueueAccessRights rights = MessageQueueAccessRights.FullControl;
   MessageQueueAccessControlEntry ace = new MessageQueueAccessControlEntry(trustee, rights);
   queue.SetPermissions(ace);
}

...

private static bool isWindowsXP() {
   OperatingSystem os = Environment.OSVersion;
   return ( PlatformID.Win32NT == os.Platform && 5 == os.Version.Major && 0 != os.Version.Minor );
}

Again, very simple and potentially error prone (what about Windows 2000 Pro?), but in my case it suffices. 

Wednesday, May 30, 2007 6:33:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Sunday, May 27, 2007

In terms of keeping this blog up-to-date on my goings on, the month of May has been a dismal one.  There has been a lot going on, but I've simply not made the time to log my activities and/or code snippets and it's eating at me.

Recently, I've been writing some code that needed to run in response to certain activities that would be triggered by another application.  These applications would not be connected, per se, in the sense that one would 'hook' into the other and respond to events.  Rather, one application would set a flag, send a message, etc such that the second application would recognize the notification and run some activity in response.

The logical choice for such an architecture is a messaging-based system.  In this case, I decided upon MSMQ/Queued Components and boy am I happy about that!  I hadn't seriously worked in MSMQ for years (though I used to do quite a bit of it) and it was fun to romp around my old playing grounds, but now with a .NET engine helping out.  Tons of fun!

This particular application is structured such that I have a web-based application (ASP.NET in this case) that will send certain messages to a message queue when the user completes some task.  Then I have a Windows Service running that will read messages from the queue and run a configurable response.  As part of the setup, I have written a few installer classes that will 1) create the message queue and 2) install the Windows Service and 3) run it automatically after install.

The task of creating a message queue installer is quite simple and straightforward.  I wanted my installer to detect the existance of the queue and create it if it wasn't found.  Upon rollback or uninstall, the queue would be deleted.  Here's an example from the Install method of my Installer class:

public override void Install(IDictionary stateSaver) {
   base.Install(stateSaver);

   try {
      const QueueName = @".\Private$\TestQueue";
      if ( !MessageQueue.Exists(QueueName) ) {
         MessageQueue queue = MessageQueue.Create(QueueName, true);
         Trustee trustee = new Trustee(@"NT AUTHORITY\NETWORK SERVICE");
         MessageQueueAccessRights rights = MessageQueueAccessRights.FullControl;
         MessageQueueAccessControlEntry ace = new MessageQueueAccessControlEntry(trustee, rights);
         queue.SetPermissions(ace);
      }
   }
   catch ( Exception er ) {
      // log the error to the event log
      throw;
   }
}

At this point, I'm ready to start interacting with the message queue by sending and receiving messages.

To simplify this process and to make it more structured, I decided to create a simple class called QueueItem.  This class provides the structure and data needed by the recipient application so that it can effectively run in response to the website's activity.  This class is also decorated with the appropriate attributes that enable it to be serialized to XML.  To further simplify the process of interacting with the message queue, the QueueItem class contains a method that allows the caller to send the message to the queue; all of the logic necessary is enclosed therein:

[XmlRoot("queueItem")]
public sealed class QueueItem {
   public QueueItem() { /* parameterless ctor for serialization support */ }
   public QueueItem(string id, string action) {
      _id = id;
      _action = action;
   }

   private string _id, _action

   [XmlElement("id")]
   public string Id {
      get { return _id; }
      set { _id = value; }
   }

   [XmlElement("action")]
   public string Action {
      get { return _action; }
      set { _action = value; }
   }

   public void SendToQueue(string label) {
      QueueItem.SendToQueue(this, label);
   }

   public static void SendToQueue(QueueItem item, string label) {
      MessageQueue queue = new MessageQueue(@".\Private$\TestQueue", QueueAccessMode.Send);
      queue.Formatter = new XmlMessageFormatter(new Type[] {typeof ( QueueItem )});

      using ( MessageQueueTransaction trans = new MessageQueueTransaction() ) {
         trans.Begin();
         queue.Send(item, label, trans);
         trans.Commit();
      }
   }
}

The Windows Service, now, is responsible for watching the queue and running the appropriate response to messages that find their way into the queue.  To accomplish this, I decided to have the service spin off a secondary thread at start up.  It's this thread that is responsible for processing messages off of the queue.

protected override void OnStart(string[] args) {
   try {
      Thread th = new Thread(new ThreadStart(processMessages));
      th.IsBackground = true;
      th.Name = "QueueListener";
      th.Start();
   }
   catch ( Exception er ) {
      EventLog.WriteEntry(Service.ActualName,
                          string.Format("Unable to start service\n\n{0}", er),
                          EventLogEntryType.Error);
      this.ExitCode = 1;
      this.Stop();
      return;
   }
}

private void processMessages() {
   try {
      using ( MessageQueue queue = new MessageQueue(@".\Private$\TestQueue", QueueAccessMode.Receive) ) {
         queue.Formatter = new XmlMessageFormatter(new Type[] {typeof ( QueueItem )});

         while ( true ) {
            using ( MessageQueueTransaction trans = new MessageQueueTransaction() ) {
               trans.Begin();
               Message msg = queue.Receive();
               trans.Commit();
               QueueItem item = msg.Body as QueueItem;
               if ( null != item ) {
                  EventLog.WriteEntry(Service.ActualName,
                                      string.Format("Message received: {0}, {1}", item.Id, item.Action),
                                      EventLogEntryType.Information);
               }
               else {
                  EventLog.WriteEntry(Service.ActualName,
                                      string.Format("Invalid message datatype received: {0}.  Expected: QueueItem.", msg.Body.GetType().FullName),
                                      EventLogEntryType.Warning);
               }
            }
         }
      }
   }
   catch ( Exception er ) {
      EventLog.WriteEntry(Service.ActualName,
                          string.Format("Critical shutdown\n\n{0}", er),
                          EventLogEntryType.Error);
      this.ExitCode = 1;
      this.Stop();
      return;
   }
}

The beauty here is that I don't have to poll.  Rather, I have the background thread call .Receive() on the queue.  This will effectively block the thread indefinitely or until a message is pushed into the queue.  At that point, it unblocks and begins processing the message.  Once finished it calls .Receive() again.  If there's a message, it gets processed, if not, it blocks.  And thus the cycle repeats itself.

Using MSMQ can be very rewarding and a lot of fun, and this little project has reminded me of that fact.

Sunday, May 27, 2007 6:51:00 PM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback