Damian Mehers' Blog Xamarin from Geneva, Switzerland.

20May/0817

Creating MSAS sinks in C# without using MediaState

Microsoft's Window Media Center has a mechanism to notify you of events inside Media Center, called the Media State Aggregation Service (MSAS).

The Media Center SDK includes a .NET assembly called MediaState, which you can use to hook up C# to MSAS, however it is possible to build C# classes that hook directly to MSAS without using the MediaState assembly.

To do so, create a C# Class Library project, and add a COM reference (Project|AddReference|Browse) to c:\windows\ehome\ehmsas.exe.

Next create a couple of classes, one called Sink and the other called Session.

Make the Sink class implement the MediaStatusSink interface from ehMSASLib imported COM library:

using ehMSASLib;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace TestMSAS {
  [ComVisible(true)]
  [GuidAttribute("360d8298-97d9-4058-9052-b91efe76d3ae")]
  public class Sink : MediaStatusSink {
    public Sink() {
      string logFile = string.Format("{0}MsasSink.log",
        System.IO.Path.GetTempPath());
      Trace.Listeners.Add(new TextWriterTraceListener(logFile));
      Trace.AutoFlush = true;
      Trace.TraceInformation("Sink started");
    }

    public void Initialize() {
      Trace.TraceInformation(("Sink.Initialize called"));
    }

    public MediaStatusSession CreateSession() {
      Trace.TraceInformation(("Sink.CreateSession called"));
      return new Session();
    }
  }
}

I've made the CreateSession method return a new instance of the Session class, and also made the Sink class public and added the ComVisible(true) attribute to make it visible from COM. You should generate and use your own Guid using Tools|Create GUID.

Make the Session class implement the MediaStatusSession interface:

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using ehMSASLib;

namespace TestMSAS {
  class Session : MediaStatusSession {
    void IMediaStatusSession.MediaStatusChange(Array tags,
                                               Array properties) {
      Trace.TraceInformation("Session.MediaStatusChange called");

      for (int i = 0; i < tags.Length; i++ ) {
        MEDIASTATUSPROPERTYTAG tag =
          (MEDIASTATUSPROPERTYTAG) tags.GetValue(i);
        object value = properties.GetValue(i);
        Trace.TraceInformation("Tag {0}={1}",
                               tag,
                               value);
      }
    }

    public void Close() {
      Trace.TraceInformation(("Session.Close called"));
    }
  }
}

We are going to put the C# assembly in the GAC, so make sure it is strongly named (Project|Properties|Signing|Sign the assembly):

image

Once you have built your project, register the resulting DLL for COM access using the regasm command, and install both the DLL, and the Interop.ehMSASLib.dll interop assembly in the GAC using the gacutil command (I missed registering the interop assembly and spent a couple of hours banging my head against the wall):

image

Finally, fire up the registry editor, find the HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{...} key for your Sink class (I searched for it to find it), and add a new KEY under the "Implemented Categories" key, with the name "{FCB0C2A3-9747-4C95-9D02-820AFEDEF13F}" (no quotes).  This tells MSAS that your component acts as an MSAS Sink:

image

To test, I generally kill the ehmsas process from the task manager, and the fire up Media Center, which restarts the ehmas process.

You can also debug directly by setting the debug executable to be c:\windows\ehome\ehmsas.exe and setting the executable paramerers to "-embedded"

Filed under: Media Center 17 Comments