In the last instalment, we looked at building a list control for Media Center. This introduced the ModelItem class, which is the basis for building the Model/View-Model in a Media Center application. With a reasonable amount of MCML now under my belt, I am shifting focus to the add-in itself. This article is designed to provide an overview of the add-in, with the topics introduced here to be the subject of upcoming posts.

As mentioned in earlier posts, the purpose of this add-in is to be able to browse and copy files from the local network onto the media center PC. The main goals are:

  • Browse local computers, shares and paths
  • Provide credentials to access network resources, if required
  • Copy files to media library folders (i.e. Pictures, Videos, Movies, Recorded TV, Music)
  • Download files sequentially in the background

Design

Class diagram for mceNetworkCopy

Entry Points and IPC

Architecturally, we need to break the add-in into two separate parts (entry points); one for the interactive portion and one to run the download manager. When the user navigates away from the interactive part of the add-in within Media Center, that process will be terminated, whereas the background process will persist. This technique is quite permissible under the Media Center SDK; it simply involves creating two different classes which implement the IAddInModule and IAddInEntryPoint interfaces, then specifying these in the registration XML file. In the diagram above, these are represented by the AddIn and BackgroundAddIn classes.

Tip: In order to stay resident in memory, entry points for background add-ins have to use ManualResetEvent (or a similar construct) to prevent the Launch() method from returning:

public void Launch(AddInHost host) {
    host.ApplicationContext.SingleInstance = true;
    mWaitForExit = new ManualResetEvent(false);
    mWaitForExit.WaitOne();
}

// ...

public void Uninitialize() {
    mWaitForExit.Set();
}

Even though both entry points are located within the same assembly, the fact that they are instantiated in separate processes means that some kind of inter-process communication is needed to communicate between them. Previously, I have used .NET Remoting in order to achieve this, however the need to explicitly extend MarshalByRefObject combined with the complexities of getting singletons to work has led me to switch to Windows Communication Foundation (WCF). Although WCF doesn’t support events like remoting does, it requires only a service contract (in the form of an interface, in this case IDownloadManager) to start serving a type (DownloadManager) remotely. (And although events aren’t supported, we can simulate their behaviour by using callback methods, which are supported.) In this design, we wrap the remote instance in a class which inherits from ModelItem, DownloadManagerProxy, so that we can bind its properties to the MCML markup on the interactive side of the add-in.

The service contract, proxy class and callback mechanism will be the subject of a future article.

Interactive Portion

The interactive portion of the add-in uses the FileList class to present the user with a list of computers, shares or directories/files, depending on the current path. The NetworkSession, NetworkBrowser and NetworkShare classes facilitate the enumeration of computers and shares, as well as allowing credentials to be used when necessary. (Note: These are 3rd-party classes – sources are listed in the section below.) These are used to determine a source path. A destination is selected by choosing from the list of MediaLibraryFolders (which resolves the media libraries in Media Center to their locations on disk) and then optionally drilling down to a subdirectory using the DirectoryList class. With a source and destination chosen, an item can be passed to the download manager:

Background Portion

The background portion of the add-in is responsible for managing downloads which are initiated from the interactive side of the add-in. The DownloadManager class maintains a queue of DownloadManagerItem objects, which represent the source, destination and status of files. When a new item is enqueued, the queue is processed asynchronously. The built-in WebClient class is used to copy the files themselves – I chose this over the copy methods in System.IO because the web client offers progress notifications.

The implementation of the DownloadManager class will be the subject of a future article.

Credentials and Password-Protected Shares

As touched on briefly, the NetworkSession class is used to access password-protected shares using credentials. It does this through impersonation, temporarily taking on the identity of the user represented by the credentials. For convenience, the add-in will retain credentials entered by the user. Since the built-in NetworkCredential class stores passwords in clear text, I designed the StoredCredential class, which holds the same information in a serialisable form, but encrypts passwords using the RSACryptoServiceProvider. Encryption provides obvious benefits, and using the crypto service provider adds the extra advantage of not having to manually create/store an encryption key – this is handled transparently by Windows.

The implementation of the StoredCredential class will be the subject of a future article.

Third Party Code

Accessing Password Protected Network Drives in C#
Provides the basis for the NetworkSession class, which allows the logged-in user to impersonate another user, given a username and password. Until the object is disposed, all normal I/O operations (System.IO) on password-protected UNC paths will use those credentials.

Retreiving a list of network computer names using C#
Used to obtain the list of computers on the local network; this code essentially does what the command-line NET VIEW tool does. Does not always include the local host, so I add it manually.

Network Shares and UNC paths
Exposes parts of the Win32 API that enumerate network shares, given a computer name. Can distinguish between file shares and other types of shares.

Get Directories Included in Windows Media Center Libraries
Provides the basis for MediaLibraryFolders, using a combination of PInvoke and Registry access to obtain the physical locations of the libraries used by Media Center.

Next Time

The next instalments will focus on the implementation of the design introduced in this article.

One thought on “Developing with the Media Center SDK, Part 5

  1. Pingback: Developing with the Media Center SDK, Part 6 | Brad Smith's Coding Blog

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required