Thinking Outside the Shell
Unified Service Desk is a very flexible tool that, along with some creativity, can do some really amazing things. In this blog, I will walk through a proof of concept with the purpose of demonstrating some lesser understood capabilities of the platform. One of the goals is to provide ideas on how to think about USD as a tool rather than an application supporting only the standard demo layout that we are all familiar with. In this exercise, I will show you how someone might get some of the benefits of USD and it's configuration system perhaps including screen pop, click to call, etc but having the users only utilize the browser. Of course, we still need to run USD but we can minimize it and put it out of view and still get a good deal of benefits without the screen aggregation.
The Final Product
To get you thinking about how you would build this solution, let me start by showing you my end result. First, I create a system tray icon that represents USD.
This system tray icon will have a context menu on it that is configurable in the USD configuration to contain just about anything you want.
In my configuration, I provided a few commands to show a browser instance (this is regular IE, not in a panel), a link to show the USD client, a link to the debugger, which opens on the floating panel, and an exit button to close USD.
If I double click on the icon or click Show Browser, the result is the same. I just open a browser to Microsoft's main website, but I also hide some of the features of the browser to discourage users from closing it. Also, if the browser is already opened and I double click the icon, it just activates my instance.
I provided an action in my custom hosted control to hide the statusbar, toolbar, location, and toolbars from the browser and it obeys the user can close option in the configuration as well. I did not choose to hide the browser's icon from the running applications, however, so the user can still close the browser by right clicking on that. Either way, if you do close the browser, you can reopen it using the same methods you used previously.
While I didn't do it in this exercise, you could also perform session management and display your sessions in your context menu, then hide and show your browser as sessions are changed, as you would expect from the USD session management. You could also add your CTI adapter to USD and have it pop your application into this browser after doing lookups and CTI navigation rules inside USD as you would expect.
How it was built
To do what I am showing in here, we need to build a custom hosted control.
I started by creating a NotifyIconControl.cs hosted control and derived from MicrosoftBase. MicrosoftBase is a simple subclass that I use to provide a convenient method of cleanly registering actions within the control rather than having a big "if" block in a DoAction override. MicrosoftBase is included in the attached so I won't talk much about it here.
First thing I did was override DesktopReady. This is the best place to do initialization in USD controls including registering the actions.
As you can see, we implement a number of actions. I will discuss these in more detail below.
ShowTrayIcon is where I want to load the icon and create the notify icon in the system tray. This is not very difficult to do. I created an icon and attached it to the resources of my project. I also want to hook the double click event to handle this as a special action.
I don't actually want to make assumptions about what the admin will want to do with my double click behavior. Some icons provide a summary view when it is double clicked. We might want to show our USD application or we might want to load the browser. In USD, it is bad practice to make such decisions in the code. The result is that our code is actually quite simple...
By simply firing the event into USD like this, the admin can now determine what will occur when the icon is double clicked. In my case, I decided to activate the browser if it is running already, otherwise, I launch the browser and navigate to Microsoft.
The AddMenuItem action populates our right click menu on the icon. I want to be creative here and don't want the admin to have to call this once for each menu item. I also don't want to hard code what options are available for the menu.
I used the split lines here that allows me to use replacement parameters to populate my menu if I wish. I also have allowed the user to specify one menu definition per line. I just step through the list and create menu items. I also support separators this way because the menu item text should be "-" for a separator.
Once the user clicks on one of our menus, we want it to do something in the system. The problem we have with a configuration driven menu like this, is how do we tell it what to do in a way that we don't have to modify the source code to handle it? It turns out to be a fairly simple problem in USD. In the click handler for the menu item, we simply fire an event with the configured name back to USD and let USD's configuration handle the behavior by running Action Calls.
ShowApplication / HideApplication
Many system tray applications hide their main window under normal circumstances. Here we want to provide actions that allow us to show and hide the main application window. It is likely you will want to call the HideApplication action in your DesktopReady event of Global Manager. This removes the icon from the taskbar leaving only the system tray icon and otherwise minimizes the window. You may then wish to show the application window when a user double clicks on the system try icon. By combining the above DoubleClick event and the ShowApplication action, the main window will be shown when double clicking on the icon. You can provide settings, reports, or whatever you wish in the main window when it comes up.
One of the tricks with a system tray based application is that you should provide a way for the user to exit the application. There is no X in the application window since it isn't displayed so we typically provide a menu option like we demonstrate here that allows the user to exit. We don't provide any special handling here but instead fire the Exit event as usual, however, we do provide an action that can be called that will exit the application. The admin may choose to do some cleanup by calling other Action Calls before exiting the application, so this also gives them the opportunity to do this.
Just having a tray icon isn't necessarily useful by itself. Likely you will still want to display the browser and get your screen pop, etc. You can always display browsers in a floating USD window, which gives you complete control but I also provide a few simple browser implementations designed for this purpose. They are called FloatingBrowser.cs, FloatingCRMPage.cs, and ChromeBrowser.cs. The first two provide actions and ability similar to how Standard Web Application and CRM Page work, except these are in the browsers themselves and not hosted in any frame. It can still inject script, get page event, etc but it's not hosted physically. The final one works with Chrome the same way. Now, Chrome does not have external programmable interfaces like IE but in this case you can at least open a chrome window with a specific URL navigated. You do not get events of any sort and script injection isn't possible. Also, another limitation is the fact that because of the way Chrome combines instances, probably for optimization, you really can only reliably control one instance of Chrome before the windows cannot be captured and re-navigated.
Attached is a sample configuration of USD you can use to set this up.
If you have a different version of USD or if you want to extend and modify the source, you can download the source and compile the USD component library at Github.