in

CodePrairie .NET

South Dakota .NET User Group

I Hate Linux

January 2008 - Posts

  • New Home Server Add-in: Tab Manager

    In yet another attempt to make the Home Server Console a little more manageable with regards to multiple tabs, Tab Manager allows a user to bypass the normal Home Server Add-in loading mechanism and display whatever tabs they want inside of another tab.

    Say what?

    Rather than having a cluttered tab tool bar full of lots and lots of add-ins:

    Home Server Console - Lots of tabs

    A user can offload the tabs they use less often to be only displayed:

    Home Server Console - With Tab Manager

    And after you've selected the tab you want, you can collapse the list:

    Home Server Console - With Tab Manager - Hidden

    All the while still making all of the settings pages in the Settings dialog (relatively) normally available:

    Tab Manager Settings

    How it works

    Existing readers of this blog will likely know that the Home Server Console looks for add-in tabs in assemblies with the following naming style: HomeServerConsoleTab.TabName.dll

    By simply renaming those assemblies (ie HomeServerConsoleTab.SomeAddin.dll to HomeServerConsoleTab.TabManager.SomeAddin.dll), the add-in will no longer be loaded automatically by the Home Server Console and through the use of some code borrowed from Test Loader, are loaded instead by Tab Manager.

    Aside from providing a new organizational home for the tabs, Tab Manager provides much of the same functionality as the Home Server Console with regards to tab ordering and ITabExtender (with the exception of ITabStatus support).

    On the Settings side of things, Tab Manager's Settings tab uses ITabExtender to create a chain of custom settings tabs (using the Next property) to provide the Settings form access to the actual settings pages in a way that it expects/can handle.

    In a later version I may offer a way to remove Settings tabs from view in a manner similar to... however I need to come up with reasonable way of doing this visually.

    Warning

    As is the case with (now) the majority of my add-ins, this add-in utilizes undocumented and unsupported mechanisms of Windows Home Server that could be misunderstood by me or change at any time possibly leading to a users Home Server no longer functioning correctly.

    This add-in is by no means done and still is in need of some polish and is not advised at this time for wide spread use.

    Please use caution with this add-in and use at your own risk.

    If you are feeling daring and want to give it a try and offer feedback... please do.

    If not, don't fret, the next version(s) will be even better thanks to those daring folks that tested out and gave feedback on earlier versions.

    Usage

    After you have installed the add-in...

    1. Launch the Windows Home Server Console
    2. Launch the Settings dialog
    3. Select the Tab Manager tab
    4. Select an assembly from the Standard Assemblies list and press the button with the Right arrow to move it to the Managed Assemblies list
    5. Repeat this process until all assemblies you want to be under the control of Tab Manager have been moved
    6. Press the OK button
    7. Click the Yes button to close the Windows Home Server Console
    8. Relaunch the Windows Home Server Console
    9. Select the Tab Manager tab
    10. Select desired tab from list.

    Assemblies listed on the Standard Assemblies list are those that are automatically loaded by the Home Server Console, while those under the Managed Assemblies list are loaded by Tab Manager instead. Moving assemblies between the lists is as simple as double clicking on the item, or single clicking and using the appropriate button to move it.

    Uninstalling this add-in does not automatically rename the modified files back to their original names. This is something I am looking into for the next version, in the mean time if/when you do decide to uninstall this add-in, you will need to add the desired files back to the Standard Assemblies list.

    Note: No file name changes are made until the settings are applied through the use of the OK or Apply buttons.

    Known issues

    • Tab Reorderer is unaware of tabs loaded through Tab Manager and can result in not all tabs being displayed on it's list or even phantom tabs without icons.
    • If loaded through Tab Manager, Tab Scroller still functions however it does not remove it's own icon.

    Both of these issues will be resolved in a later version that will include the functionality of Tab Reorderer and Tab Scroller being added natively to Tab Manager (and reduce my add-in count from 5 to 3).

    • Any add-in that exposes status information (ie the main Microsoft tabs) will still work, however no status bar information will be displayed.
    • Some third-party add-ins that expect a given assembly name may not be able to load/save their settings.
    • Non-English systems may have issues loading the correct language for localized add-ins.

    Downloads

  • Updated: WHS Test Loader

    Due to the recent news that WHS add-in's must start with a capital letter (HomeServerConsoleTab.TabName.dll (correct) vs HomeServerConsoleTab.tabName.dll (incorrect))... I've updated WHS Test Loader (instructions) to also check for this condition.

    Downloads:

  • Star Trek XI Teaser

    Apparently someone snuck a camera into a recent showing of Cloverfield and got this:

    Oh what chills ran down my spine when the theme began to play.

  • Coming Soon: Tab Management

    Last month I mentioned a proof of concept add-in I was working on to change the way a user looks at some of the tabs in the Home Server Console.

    I'm pleased to say that this add-in still proceeds (granted fairly slowly over the last month) and with any luck will be available in an early form before too long.

    It works quite well today... only it needs a little more polishing, eye candy (not to mention a fair bit more testing) before I'll make it available.

    The current build gives a better look when expanding and hiding the secondary tab list.

    Expanded:

    Tab Management - Main View

    Hidden:

    Tab Management - Hidden

    Part of the delay was figuring out a good way to not display tabs in the main console view... but still make them available in the Settings panel:

    Tab Management - Settings

    A bit of work remains with regards to preserving existing tab order (on both sides) as well as other general sorting.

  • Amazing New Add-in: Disk Management

    After first seeing the announcement of Sam Wood's new Disk Management add-in I cursed at being beaten out of the door with a tool to help a user figure out which drive is which in their Home Server Console as my attempt kept getting pushed back due to other priorities.

    Then I used it... and was thrilled, and floored.

    Not only does it provide a fairly nice user interface, it also includes some undocumented functionality for adding and removing disks making it (in some parts) a replacement for the Storage Management tab.

    Great job Sam!

    Links:

    One other fairly impressive thing about this is that Sam isn't just a WHS add-in author... but also a blogger on the subject of 4GW (4th Generation Warfare).

    (Take a look at this this quick post from my buddy Dan (aka tdaxp) for a quick primer on the generations of warfare)

    Part of what makes the subject so interesting (as well as the talk of 5GW) is that many of it's implications also have parallels in software development with regards to overall agility of strategy and resources.

  • Suddenly I care about VS2008 SP1

    ... and Visual Studio 2008 hasn't even hit retail shelves yet.

    From the sounds of it... the bug in VS 2005 and 2008 (at least) that prevents proper automatic specification of the new project's assembly name based on the settings of the project template will be included in Service Pack 1 for Visual Studio 2008.

    Huzaah!

    While this kind of bug thankfully doesn't affect many (hence why it seems to have gone largely unnoticed until recently), it does get in the way of users of my my Windows Home Server Add-in Project Templates or any other template that requires specific naming of the output assembly... leading to the developer having to manually rename the assembly (as specified in the Project properties) whenever they create a new project.

  • WHS Dev Tip #15: Terminal Services

    Did you know the Home Server Console uses the Remote Desktop Protocol/Terminal Services to bring the application to clients? Did you know that you can launch additional applications in the session?

    Terminal Services

    Before getting into what we can do... lets make sure we all understand what we are using...

    Windows Terminal Services is a server component dating back to NT4 which allows remote machines to connect to a server and be presented with a (nearly) fully functional desktop where a user can do their work almost as fast and easily as if it was local without having to having access to anything more than a client app (available as either a desktop app or ActiveX control) and a network connection.

    We saw this same technology brought to Windows XP for it's Remote Desktop feature and now in Windows Home Server for both normal Console use as well as more complicated administration.

    Using Remote Desktop

    Ordinarily when we want to connect to our Home Server to do administrative tasks that cannot be achieved in the Home Server Console, we'll do the following:

    1. Launch the Remote Desktop client
      • XP/2003: Start -> Run -> mstsc
      • Vista/2008: Start -> mstsc
    2. Specify server name/address
    3. Click the Connect button
    4. Provide credentials and click the OK button.

    This is the simple way to connect and with default options. The client and protocol have many more options than we normally use.

    Regular Connect

    Startup Program

    Rather than connecting to a new (or existing) user session on the server complete with desktop and start menu, we can instead request that a specific application (on the server) be launched on the server, to do so we need only:

    1. Click the Options button on the main Remote Desktop Connection Window
    2. Select the Program tab
    3. Check "Start the following program on connection"
    4. Specify a program or file

    Once done, we can do something a simple as launch the Windows Calculator right away when we connect...

    Calculator

    Calculator in RDP

    Or even just the Windows Home Server Console:

    Start program

    Console in regular Remote Desktop

    The only thing missing (aside from the parent client window being sized better) is the removal of the window frame... which can be achieved by throwing in the -b argument:

    Resized

    That's right... the WHSConsoleClient application on WHS client PC's is largely just a fancy Terminal Services client that executes "homeserverconsole.exe -b" on the server on connect as well as provides the plumbing to make IConsoleServices.OpenHelp() and IConsoleServices.OpenUrl() calls be passed back to and launched on the client.

    With this in mind we have a number of possibilities.

    Warning

    Before going any further I want to make clear that what I will be describing below is completely unsupported by me and by Microsoft and can result in loss of key files.

    This information is provided for informational purposes only and for those who wish to do some hacking of their own server. Nothing in this post should be used as part of any add-in or other software on Home Server's that are not owned by reader of this post and author of said add-in or software.

    Replacement

    The simple method is simply to rename (and backup) HomeServerConsole.exe on the server and put in it's place an application of our choice or design that can handle being used in the strange window size used by the Home Server Console.

    It's interesting to note that HomeServerConsole.exe like a good number of the Home Server files are not protected by Windows File Protection, nor is there any other security mechanism in place to prevent a malicious user from replacing HomeServerConsole.exe with their own application.

    So what should we replace it with?

    One method

    I find myself often using the Remote Access web site to connect to my main desktop PC and sometimes need to do something on my Home Server... which requires launching one Remote Desktop connection inside of another one.

    While this works... it's certainly not ideal. Instead what if we were to launch Windows Explorer in the same Terminal Services session that we have the Home Server Console in?

    As easy as this would be with an add-in... a problem we have is is that the Console is displayed there without a Window frame or title bar...

    So one option would be something like this:

    class Program
    {
       static void Main(string[] args)
       {
          string initalProgram = TerminalServices.GetInitialProgram(Process.GetCurrentProcess().SessionId);
     
          //In Home Server Connector?
          if (initalProgram.ToLower().StartsWith("homeserverconsole"))
          {
             //then launch explorer
             LaunchExplorer();
          }
     
          //Launch the Home Server Console anyway.
          LaunchHomeServerConsole();
       }
     
       static void LaunchHomeServerConsole()
       {
          Process.Start(@"C:\Program Files\Windows Home Server\HomeServerConsole1.exe");
       }
     
       static void LaunchExplorer()
       {
          Process.Start(@"explorer.exe");
       }
    }

    In the above code, I use some methods from the Terminal Services API to determine if the session our app is running in was asked to launch the Home Server Console, if so we'll launch the real thing (named HomeServerConsole1.exe in this example) as well as a copy of Explorer... otherwise we'll just launch the Home Server Console.

    The actual check for to determine the startup application involves a call to WTSQuerySessionInformation() with the WTS_CONFIG_CLASS.WTSUserConfigInitialProgram enumerated value.

    As simple and as workable as this is... it does have a major flaw... the Home Server Console expects to be named HomeServerConsole.exe for any number of operations including access to it's .config file. Instead of launching a new processes.. an alternative is to load the assembly containing the real thing and launch it within our own application (gotta love .NET reflection):

    static void LaunchHomeServerConsole()
    {
       Assembly whsConsole = Assembly.LoadFile(@"C:\Program Files\Windows Home Server\HomeServerConsole1.exe");
       whsConsole.EntryPoint.Invoke(null, new object[] { new string[0] });
    }

    Note the above code is remarkably slow on my WHS when it comes to launching the Home Server Console... resulting in a load time of several minutes, something I have not spent much time debugging as yet.

    Home Server Console with Explorer

    Improvements

    With a little additional work, we could enumerate the currently running processes (with WTSEnumerateProcesses() ) and determine if an instance of explorer is already running, and if not launch one.

    The Future

    Likely this method will only work so long as there is no protection of the WHS files, although should that not change this option will be even more powerful should the next version of Windows Home Server be based on Windows Server 2008 and use TS RemoteApp for displaying of the Home Server Console.

    Sample

    No sample this week as this post is intended to be more theoretical and informational rather than practical.

    Hopefully this has given you some ideas of how you could use this on your own.

    Conclusion

    With a little use of the Terminal Services API and a bit of file renaming it is possible to execute ones own custom code prior to the Home Server Console being launched, giving numerous options for additional customization of the Windows session that the Console is loaded in... be it launching Windows Explorer, other applications or applying custom external settings to the Home Server Console.

    Next Time

    Hacking the Home Server Console (in place) using reflection.

    As always though, I'd love to hear your ideas of what you'd like to see in future.

    Note: The information in this post is based on undocumented and at times deduced information on Windows Home Server and is not officially supported or endorsed by Microsoft and could very easily be wrong or subject to change in future, so please take it and everything else said on this blog with a grain of salt and use with caution.

  • WHS Dev Tip #14, ITabExtender, Part 4: Tab Status

    Plenty of times we've seen the little status notifications at the bottom of the Home Server Console telling us who is logged in through the remote access web site or the status of the storage balancing:

    StatusBarStrip - Logged in and balanced

    How would you like to put your own information there? With ITabExtender it is possible.

    A word of warning

    Before digging into how this can be done it needs to be made very clear that unlike all of the other features of ITabExtender that I've discussed so far this week, having a third-party add-in expose status information using ITabExtender is dangerous as the Home Server Console only has a few places to display such information, places that are normally used by the Microsoft tabs... potentially leading to a third-party add-in visually overwriting important information.

    Ideally if a third-party does implement ITabExtender and does make use of the status functionality they don't distribute the add-in and instead just use it for in house functionality and testing... and should later they decide to share it, they disable the status functionality.

    Status

    An ITabExtender exposes the read only Status property which returns an object that implements the ITabStatus interface which defines the following:

    • OnClick()
    • StatusEvents()
    • StatusImage
    • StatusNext
    • StatusOrdinal
    • StatusText

    Right off the bat we can create a custom class that implements this interface:

    public class TabStatus : ITabStatus
    {
       public void OnClick()
       {
     
       }
     
       public void StatusEvents(System.Diagnostics.EventLog whsEvents)
       {
     
       }
     
       public Bitmap StatusImage
       {
          get
          {
             return Properties.Resources.DefaultToolBarIcon16;
          }
       }
     
       public ITabStatus StatusNext
       {
          get { return null; }
       }
     
       public int StatusOrdinal
       {
          get { return 0; }
       }
     
       public string StatusText
       {
          get { return "Some Status: " + DateTime.Now.ToString(); }
       }
    }

    An alternative to implementing a stand alone class is to have our implementer of ITabExtender also implement ITabStatus to allow for easier setting and monitoring of status values.

    For simplicity this post and the later example add-in build them as two separate classes.

    StatusImage & StatusText

    Similar to IConsoleTab, ITabStatus expose a pair of properties that define the image and text that should be associated with.

    A quick note is that while TabImage is expected to return a Bitmap that is 32x32 pixels in size, StatusImage is expected to return a bitmap that is 16x16 pixels in size.

    StatusOrdinal

    The status bar along the bottom of the Home Server Console is an instance of the custom StatusBarStrip control which contains 3 separate StatusBarButton instances; the first for Remote login notification, the second for storage balancing status and the third for backup/restore progress.

    The StatusOrdinal property of an ITabStatus implementer specifies which StatusBarButton that the status will be displayed on (0-2).

    StatusEvents()

    Rather than setting up some messaging system using named pipes, remoting or other a simple option is used with ITabStatus... the event log.

    StatusEvents is called once, not long after a the Status property is first read, passing in a reference to the HomeServer event log... enabling the receiver to parse the log looking for specific events as well as use the EntryWritten event to be informed with a new log entry is written.

    OnClick()

    OnClick() is an interesting case... and one that I do not believe was implemented in any of the Microsoft tabs, despite it's existence (or at least support of it) causing a visual bug, it still sorta works and will still be discussed here.

    OnClick() is treated like an event handler that is raised when a user clicks the StatusBarButton that is being used by an ITabExtender... only simply clicking the mouse on it isn't enough, instead you have to press the space bar to cause the click to actually occur.

    StatusNext

    Likely intended to be similar in functionality to ITabExtender.Next for ITabStatus instances... this work appears to be only half complete as nothing I have done has been able to use this to display multiple ITabStatus instances without employing multiple tabs.

    Updating

    Like many of the other undocumented features of the Home Server Console, changing the visual look of the ITabStatus implementer isn't as simple as just updating the applicable property, instead we need to request that the StatusBarStrip update the status for us.

    In order to accomplish this the static CommonState class (Microsoft.HomeServer.Controls, HomeServerControls.dll) exposes a property named MainStatusBar which references the StatusBarStrip at the bottom of the main form... giving us access to a SetStatus() method that requests that this be done.

    So from our Home Server Console tab (ideally) we need to call SetStatus and pass in a reference to the tab whose status we want to update:

    CommonState.MainStatusBar.SetStatus(this);

    After that the Console takes care of the update for us.

    Remember though that any update will overwrite any existing updates to the same StatusOrdinal, potentially throwing out important information... just as the information placed there by us can be overwritten by a call to SetStatus() from another add-in.

    Another potential issue that can be encountered with updating is removing the status information once it's no longer relevant (ie a user is no longer logged into the system via the web page). One possible option is to remove the existing ITabStatus instance and have ITabExtender.Status return null/Nothing and then call CommonState.MainStatusBar.SetStatus(this). This method will not cause a visual change, instead a more workable option  is to change the StatusText and StatusImage properties of the ITabExtender to return and empty string and null/Nothing respectively for the update to actually occur.

    Settings

    Because the Settings form does not have a StatusBarStrip on it, the ISettingsExtender.Status property is largely worthless for tabs on the Settings side of things.

    Sample

    At long last... a pair of demo applications that demonstrate the functionality that's been discussed this week.

    In each project are six tabs for the main console window that implement the ITabExtender interface that also display the time the last time Refresh() and Prepare() methods are called on it.

    Similar functionality exists (sans Refresh() and Prepare() functionality in the settings window with three tabs that implement the ISettingsExtender interface.

    On the first tab there are three buttons that allow enable the tab to output a status message, refresh that message and disable that message (which requires one last refresh).

    All the while all tabs specify a unique TabOrdinal to ensure that they are displayed in order one after another.

    ITabExtender Demo - First Tab

    Downloads:

    Conclusion

    ITabExtender through ITabStatus provides a relatively easy to use mechanism for a tab to display additional information to the user. Unfortunately because ITabExtender and ITabStatus were never intended for end user use, conflicts can easily exist between existing status messages either overwriting or being overwritten by status messages from third-party add-ins.

    Next Time

    Replacing the Home Server Console with our own application to give us just a little more control over our system when working remotely.

    As always though, I'd love to hear your ideas of what you'd like to see in future.

    Note: The information in this post is based on undocumented and at times deduced information on Windows Home Server and is not officially supported or endorsed by Microsoft and could very easily be wrong or subject to change in future, so please take it and everything else said on this blog with a grain of salt and use with caution.

  • WHS Dev Tip #14: ITabExtender, Part 3: Multiple-Tabs

    Under the current tab model we are familiar with... the Home Server Console looks for a class named HomeServerTabExtender in a namespace based on the name of the assembly (ie HomeServerConsoleTab.MyTab.dll holds Microsoft.HomeServer.HomeServerConsoleTab.MyTab) for information on the display of a given Console add-in.

    As simple as this system is, it is extremely limiting as it means that an assembly can only contain a single tab, which leads to multiple assemblies being required for a more complicated add-in that might require multiple tabs (such as in Settings), ITabExtender changes that.

    Next

    ITabExtender defines a read-only property named Next which returns another ITabExtender, enabling a programmer to create a linked-list of add-in tabs with remarkable ease.

    Lets look back at the code sample from Monday of the extra properties and methods we get with ITabExtender over IConsoleTab:

    public ITabExtender Next
    {
       get { return null; }
    }
     
    public void Prepare()
    {
       
    }
     
    public void Refresh()
    {
       
    }
     
    public ITabStatus Status
    {
       get { return null; }
    }
     
    public int TabOrdinal
    {
       get { return 33; }
    }

    Right now Next is just returning null... in order to return something useful we first need to create another class that implements the ITabExtender interface, create an instance of it and return it. Unlike with the main class, this time though we can choose an arbitrary name and put it in any namespace we want:

    public class ExtraConsoleTabClass : ITabExtender
    {
       private IConsoleServices consoleServices;
       private MainTabUserControl tabControl;
     
       public ExtraConsoleTabClass(int width, int height, IConsoleServices consoleServices)
       {
          this.consoleServices = consoleServices;
     
          tabControl = new MainTabUserControl(width, height, consoleServices);
     
          //Additional setup code here
     
     
     
       }      
     
       #region ITabExtender Members
     
       public ITabExtender Next
       {
          get { return null; }
       }
     
       public void Prepare()
       {
          
       }
     
       public void Refresh()
       {
          
       }
     
       public ITabStatus Status
       {
          get { return null; }
       }
     
       public int TabOrdinal
       {
          get { return 34; }
       }
     
       #endregion
     
       #region IConsoleTab Members
     
       public bool GetHelp()
       {
          return false;
       }
     
       public Guid SettingsGuid
       {
          get { return Guid.NewGuid(); }
       }
     
       public Control TabControl
       {
          get { return tabControl; }
       }
     
       public Bitmap TabImage
       {
          get { return Properties.Resources.DefaultToolBarIcon; }
       }
     
       public string TabText
       {
          get { return "Extra Tab"; }
       }
     
       #endregion
    }

    Note: You are free to create your lower classes/tabs anyway you like, I prefer sticking to the same conventions and constructors as in the parent tab for simplicity.

    At this point all we need to do is wire up the new ITabExtender with the one that will be automatically found by the Home Server Console... and in order to do this all we need to do is create an instance of the new class, store it some where and spit it back out when the Next property is read:

    ExtraConsoleTabClass extraTab;
     
    ...
     
    public HomeServerTabExtender(int width, int height, IConsoleServices consoleServices)
    {
       this.consoleServices = consoleServices;
     
       tabControl = new MainTabUserControl(width, height, consoleServices);
     
       //Additional setup code here
     
       extraTab = new ExtraConsoleTabClass(width, height, consoleServices);
     
    }
     
    ...
     
    public ITabExtender Next
    {
       get { return extraTab; }
    }

    And when it's all said and done (and loaded in the Home Server Console) we are greeted with our two tabs:

    ITabExtender - Two Tabs

    Because this method works just like a (read only) linked-list, we can do it almost indefinitely (provided we remember that the Home Server Console only supports a finite number of tabs):

    ITabExtender - Six Tabs

    A word of warning though... do not have an ITabExtender refer to itself... or have any kind of circular dependency in your tab set as it will run indefinitely and cause the Home Server Console to take quite a while to load as it waits for your add-in to fail.

    Settings

    Like so many of the other features of ITabExtender, the same functionality works with ISettingsExtender when used in the settings dialog:

    ISettingsExtender x3

    Sample

    A sample add-in demonstrating everything discussed here will be part of the last post on Thursday.

    Conclusion

    ITabExtender and it's Next property enables programmers to easily define multiple tabs in a single assembly, offering the opportunity to visually break one large and complicated add-in into smaller and more manageable sub components that can each be represented by their own tab, keeping in mind the whole while that the Windows Home Server Console only supports a finite number of tabs.

    Next Time

    Tomorrow: Tab status.

    Note: The information in this post is based on undocumented and at times deduced information on Windows Home Server and is not officially supported or endorsed by Microsoft and could very easily be wrong or subject to change in future, so please take it and everything else said on this blog with a grain of salt and use with caution.

  • WHS Idea: Silverlight Uploader

    After the announcement of Power Pack 1, on10 posted an interview yesterday with Windows Home Server Product Planning Manager Todd Headrick discussing it and it's relation to overall Home Server development (ie it sounds like PP1 will be alone for the time being and focus will move to the next major version)

    One of the discussed features was the new that the new upload mechanism that borrows code from the Windows Live SkyDrive team and their upload mechanism... which is currently only supported on IE6 and IE7.

    Granted I'm a IE7 user... I'm rather surprised to see that there is no similar option for Windows based FireFox users... let alone the half a dozen Macintosh users out there or that one Linux guy in the corner thinking he's not alone.

    Then it hit me... how soon until something similar based on Silverlight?

    I've little doubt that after the final 2.0 release and it's itty bitty CLR that the Home Server Team will support Silverlight it in one way or another either in the current or a future version of Windows Home Server... but why should that stop some clever third party developer who wants to create that add-in that supports the current alpha code (or upcoming beta code).

    No... that developer wont be me. I've got a couple other things on my plate before I sit down to learn Silverlight.

  • WHS Dev Tip #14: ITabExtender, Part 2: Tab Refreshing

    As easy as it is to create a tab for the Windows Home Server Console, something's are difficult. Needlessly so at times.

    Should a programmer want to know when their tab is being displayed they might watch for their Controls ParentChanged or reflect against the larger console for other ways.

    Shouldn't there be an easier way?

    In many applications the F5 key can be used to refresh visible data. Same goes for some tabs in the Home Server Console and should a programmer use the KeyDown or KeyPress events to listen for it they will find themselves out in the cold because the Home Server Console handles the keystroke itself and doesn't pass it down the line.

    Shouldn't there be an easier way?

    Both of these issues are resolved with two methods provided by ITabExtender: Prepare() and Refresh()... a pair of options that should have been provided in IConsoleTab in the opinion of this humble blogger.

    Refresh()

    Some add-ins are expected to be able to refresh the displayed data from time to time and because the Home Server Console suppresses any F5 keystrokes making any hooks into KeyDown or KeyPress worthless, an alterative is to use an external mechanism for refreshing such as a timer or a manual refresh button... ITabExtender.Refresh() is our saving grace.

    Beyond the requirement of implementing a stub at least for the method, how Refresh() goes about updating an add-ins control is completely up to the programmer.

    Ideally used as a location to trigger a control wide refresh in a manor that the designer controls.

    Prepare()

    Along with Refresh() which is called just as our tab is being displayed and on the F5 keystroke we also get Prepare() which is executed far less... only when a tab is about to be displayed.

    For some applications, having a Prepare() and Refresh() method may seem superfluous, after all, isn't Refresh() called shortly after Prepare()? (Yes)

    Having the two separate methods gives us the opportunity to localize our logic a little better, as well as to implement only what we need.

    While Refresh() gives us the opportunity to refresh our data on demand from the user, we may only want to allow refreshing (due to cost) once at tab selection time.

    Perhaps we have two different levels of refreshing, a full refresh that we want to occur on tab selection and a mini-refresh whenever the user presses F5.

    It's these kinds of questions that need to be taken into account when using ITabExtender and deciding how functional to make Refresh() and Prepare().

    I do want to pause and say that I do kind of wish that there was an official third method... a Postpare() or Cleanup() that tells the programmer when a new tab has been selected, giving an opportunity to turn off any expensive live polling they may have enabled in Prepare().

    Settings

    While Prepare() and Refresh() are exposed as part of ISettingsExtender, only Prepare() is ever called, and that happens only when the form is loaded either through the Settings button being pressed or programmatically from an add-in calling IConsoleServices.OpenSettings().

    As nice as it would be to allow for the same automatic refreshing of data in Settings as we now have access to in the main form, I suspect that this was a design decision based on the idea that the state of settings should only be changing based on explicit user input (ie clicking a button or typing in new values), removing the importance of this.

    Sample

    A sample add-in demonstrating everything discussed here will be part of the last post on Thursday.

    Conclusion

    ITabExtender provides an easy way to for an add-in to be notified when it is about to be displayed and later requested to be refreshed by the user through the Prepare() and Refresh() methods respectively.

    Next Time

    Tomorrow: Multiple-tabs.

    Note: The information in this post is based on undocumented and at times deduced information on Windows Home Server and is not officially supported or endorsed by Microsoft and could very easily be wrong or subject to change in future, so please take it and everything else said on this blog with a grain of salt and use with caution.

  • WHS Dev Tip #14: ITabExtender, Part 1: TabOrdinal

    A little secret is buried away in the Windows Home Server Console, a secret so useful it should have been officially documented and made available to the coding public long ago (in the opinion of this humble blogger) with a couple of tweaks.

    This secret... ITabExtender (Microsoft.HomeServer.Extensibility, HomeServerControls.dll).

    An extension of IConsoleTab, ITabExtender provides numerous options that many wish they had already... the ability to specify a tab's location, refreshing, notification just prior to the tab being displayed... even external status notification and multiple tabs in a single assembly.

    All of these gems are made possible with ITabExtender, a topic I'll be discussing over the next 4 posts which will cover in the following order:

    1. TabOrdinal
    2. Tab Refreshing
    3. Multiple-Tabs
    4. Tab Status

    Using ITabExtender

    In order to use ITabExtender, we first need to add a reference to HomeServerControls.dll and can use the interface in place of (or in addition to) IConsoleTab:

    public class HomeServerTabExtender : IConsoleTab, ITabExtender

    Once done we will need to fully implement the interface which includes the following additional properties and members:

    • Next
    • Prepare()
    • Refresh()
    • Status
    • TabOrdinal

    Visual Studio will can generate the methods for us by right clicking on the interface and selecting Implement Interface. Once done we'll need to take a moment to cleanse the new methods and remove their raising a few exceptions informing you that the method hasn't yet been implemented and make the code null when applicable... bringing our additions to:

    public ITabExtender Next
    {
       get { return null; }
    }
     
    public void Prepare()
    {
       
    }
     
    public void Refresh()
    {
       
    }
     
    public ITabStatus Status
    {
       get { return null; }
    }
     
    public int TabOrdinal
    {
       get { return 33; }
    }

    Once added and cleansed the add-in will be compilable and usable, now we want to use it for it's advanced features.

    TabOrdinal

    In the code featured above, in only one of the properties or methods are we doing anything or returning anything of use. In the TabOrdinal property a value is returned which is used to specify it's location in the Home Server Console... within reason.

    As specified by the Changing the Tab Order page on MSDN, tab positions 2-32 are reserved for Microsoft... this is not merely a suggestion but an absolute requirement. If in your ITabExtender you specify a TabOrdinal inside of the range reserved for Microsoft it will likely not be displayed at all.

    Outside of that range though we are pretty free to specify what we want and where... just remember that the general order of tabs in the Home Server console is as follows:

    1. OEM tab(s)
    2. Microsoft Tabs
    3. Tabs with specified location
      1. ITabExtenders
      2. Through HomeServerConsole.exe.config file
    4. All other tabs

    At times a conflict may occur where one or more tabs have the same number or none at all, in such cases the disputed tabs inserted in alphabetical order.

    This means that a tab that implements ITabExtender will ordinarily appear earlier in the list than the average add-in that does not implement it and does not have it's location overridden through the .config file.

    As nice as it might be to have ones own add-in be nice and early in the list, chances are that all users may not agree and instead the user would be forced deal with an undesirable situation, manually change the order, use an add-in to change the order, or remove the offending add-in outright.

    Care must be taken when using ITabExtender.TabOrdinal so as not to annoy the end user and not assume that our add-in is the end all be all (even if it is).

    Settings

    All of the discussion previously has been with regards to a tab for the main Home Server Window. On the settings side of things the ISettingsExtender (Microsoft.HomeServer.Extensibility, HomeServerControls.dll) interface exists and does much the same job the same job as ITabExtender (even inheriting from it) and TabOrdinal works the same way in the Settings dialog as it does in the main form.

    Sample

    A sample add-in demonstrating everything discussed here will be part of the last post on Thursday.

    Conclusion

    ITabExtender allows a programmer the useful ability to specify a tab index of their own. This should however only be done with the knowledge that end users may not agree with the ordering as specified by the programmer and may become annoyed by a new add-in forcing itself ahead of all others even if such positioning is changeable.

    Next Time

    Tomorrow: Tab refreshing.

    Note: The information in this post is based on undocumented and at times deduced information on Windows Home Server and is not officially supported or endorsed by Microsoft and could very easily be wrong or subject to change in future, so please take it and everything else said on this blog with a grain of salt and use with caution.

  • Windows Home Server Power Pack 1

    As you already now know, the Windows Home Server team has announced Windows Home Server Power Pack 1.

    I like this... big time.

    Not only does it mean that the long awaited 64-bit connector software will soon be ours (soon being sometime during the vague 'first half of 2008'), but also that Windows Home Server is not a normal product that you buy and get bug patches for... but is also one that (in theory) Microsoft will be extending over time as well (granted, Power Pack 1 could end with a similar fate to Quake II Netpack 1: Extremities (ie being the only pack)).

    As useful as 64-bit support (for my Media Center box) and the other added features will be, I think the most important part of PP1 (for me) is going to be the ability (or at least a mechanism to attempt) to prepare a corrupted backup database as I've had plenty of issues with this (I still suspect them to be hardware related) and the only way to resolve the error is to completely wipe out all backups or the entire WHS.

  • Multiple OEM Home Server Tabs

    The Windows Home Server Console reserves the left most tab position to a tab supplied by the OEM who builds the actual Windows Home Server... such as what is seen in the HP MediaSmart server:

    mediasmart-server

    Did you know that you can specify your own?

    It's simply a matter of breaking out the HomeServerConsole.exe.config file on the server and specifying an appSettings key and value based on the name of the tab in question.

    For me to set my Web Folders add-in to show up as the OEM tab my config file could be as simple as this:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <appSettings>
            <add key="Web Folders" value="1" />
        </appSettings>
    </configuration>

    Once done the third party tab you've specified will show up in the OEM position:

    Web Folders as OEM Tab

    Did you know that you can specify more than 1 OEM tab?

    Just use the same trick in the config file... only do it again for other tabs:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <appSettings>
            <add key="Web Folders" value="1" />
            <add key="DHCP Server" value="1" />
        </appSettings>
    </configuration>

    DHCP and Web Folders as OEM Tabs

    Just remember that when two tabs have the same numerical value, their display names are used to sort them alphabetically.

Powered by Community Server (Commercial Edition), by Telligent Systems