The HelpDesk Administration Explorer

Robert Coleridge
Microsoft Developer Network Technology Group

December 1997
Updated: February 2, 1998

Click to view or copy the samples for this technical article.

Introduction

This article will discuss the administration application of the HelpDesk sample. The HelpDesk Explorer (HDExplr) was created using Microsoft® Visual Basic® version 5.0 (with Service Pack 2) and requires the HelpDesk components: HDAdmin.dll, HDClient.dll, HDServer.dll, and DBExec.dll. HDExplr was written to follow standard n-tier design and methodologies.

The HelpDesk Administrator

For our purposes, a HelpDesk administrator is one or more people within a business, business unit, or institution who have the responsibility and authority to make decisions that affect the performance and operation of the HelpDesk; specifically, the HelpDesk administrator maintains the various tables and domains within the HelpDesk database.

Technician Maintenance

Each technician has certain properties, such as location and skill, that help determine how HelpDesk assigns requests to a particular technician's queue. The administrator can change these properties dynamically with HDExplr. These changes are effective immediately and affect what requests a technician receives the next time unclaimed requests are reassigned. (For more information on how requests are assigned and reassigned, see Steve Kirk's "Task Distribution in a Customer Service System.")

Domain Maintenance

A domain is a lookup table within the database. These tables change infrequently and are generally used to populate the various client interfaces of the HelpDesk sample. For example, a table containing a set of predefined locations, priorities, or skills would be a domain. Although these tables can be deleted from, they are usually appended to. (For an explanation on how to delete from a domain, see the Appendix of the MSDN Online version of this article.)

System Performance

This area covers the more esoteric functions of a HelpDesk administrator. With HDExplr, the administrator can:

Database Security

Secure access to the HelpDesk database is maintained via the Microsoft SQL Enterprise Manager. We have taken a minimalist approach in that only users entered in the SQL logon database are considered administrators and are allowed to use HDExplr. For access to the user clients and the technician clients, we are simply using the standard Microsoft Windows NT® authentication security.

Although this area is critical to the security of the HelpDesk data, the actual maintenance of the security privileges is beyond the scope of this article. For further reading, see "Managing Security" in the Data Access Services section of the Platform SDK documentation.

The HelpDesk Explorer

The HelpDesk Explorer (HDExplr) allows an administrator to modify the HelpDesk tables and change any system parameters. The following is a discussion of the functionality of HDExplr and the new HDAdmin.dll COM component that works with it.

HDAdmin

The HDAdmin component's methods and properties could have been added to the HDClient component, which services all the HelpDesk client applications, but it would have increased the size of the component without a proportionate increase in functionality for the end user. So, in order to keep HDClient as thin as possible, HDAdmin was created separately.

HDAdmin does not supercede HDClient, however. The two components work side by side. In fact, HDExplr uses the HDClient component more than the HDAdmin component. The HDAdmin component supplies the administrator specific functionality. Figure 1 diagrams where HDAdmin fits in with the existing HelpDesk object model.

Figure 1. HelpDesk object model

HDAdmin.dll has objects that provide access to the administrative tables and data. Table 1 lists three of these new objects.

Table 1. HDAdmin Objects

Name Type Description
CAdmin object Administrator/controller for the entire DLL
CSysParm data object Encapsulates creation and manipulation of the SysParm table
CSysParmType data object Encapsulates creation and manipulation of the SysParmType domain

And the methods in Table 2 can be found in the CAdmin object.

Table 2. CAdmin Object Methods

Name Type Description
GetSysParms Method Returns a collection of CSysParm records
GetSysParmTypes Method Returns a collection of SysParmType records
Init Method Used to initialize the HDAdmin.dll
Refresh Method Used to force a refresh of the internal collections and tables
Term Method Used to release the resources acquired by HDAdmin.dll prior to termination

Creating the HelpDesk Explorer

HDExplr is designed in a Windows Explorer style. The skeleton of HDExplr is created through the Visual Basic VB Application Wizard:

  1. Click New Project from the File menu, and then click VB Application Wizard.

  2. At the first dialog box (Introduction), click Next. In the Interface Type dialog box, select the Explorer Style option and click Next.

  3. The HDExplr application requires all the available menus, so click Select All, and then click Next.

  4. HDExplr has its string in a resource file, so click Yes, type HDExplr.rc for the filename, and click Next.

  5. HDExplr provides a Web browser interface, so click Yes, type your desired Universal Resource Locator (URL), and click Next.

  6. Select all available forms from the Standard Forms dialog box and click Next.

  7. In the Data Access Forms dialog box, select No, as the HDExplr uses data objects for its data access, and then click Next.

  8. Click Finish. You now have most of the code needed to create the HDExplr application.

The Main Screen

Although the VB Application Wizard generated most of the presentation code for the HDExplr, the code to populate the main screen and respond to user requests must still be added.

The HDExplr panes

The main screen is divided into two panes. In the left pane is a tree view that will contain the various components of the HelpDesk, for example, technicians, domains, and system parameters. The right pane will provide a display of the records or contents of that component, for example, all the Location records, or all the system setup parameters. For clarity, let's call the left pane the Component pane, and the right pane the Contents pane.

Figure 2 gives an example of what the display would look like if the Technicians component were selected. The Contents pane displays the Technician records so that they can be examined or modified.

Figure 2. HDExplr panes

Populating the panes

Let us examine how each pane is populated with data.

By examining the following code, you can see that populating the Components pane is straightforward. Simply populate an ImageList control with bitmaps from the resource data for the various images that are needed. Then add entries to the tree, specifying the node name, its relationship within the tree, and other relevant data. Note that in order to maintain a localizable application, heavy use was made of LoadResString to load data from the resource data segment of the application.

. . .
' Set the Treeview control properties.
tv_ComponentTree.LineStyle = tvwRootLines  ' Linestyle 1

'Initialize vars and values from the resource file.
m_tvPathSep = tv_ComponentTree.PathSeparator
m_Node_Domains = LoadResString(icIDS_KWTV_DOMAINS)
m_Node_Technician = LoadResString(icIDS_KWTV_TECHNICIAN)
m_Node_location = LoadResString(icIDS_KWTV_LOCATIONS)
. . .
m_Node_DomainLocations = m_Node_Domains & m_tvPathSep & m_Node_location
m_Node_DomainPriorities = m_Node_Domains & m_tvPathSep & m_Node_Priority
m_Node_DomainSkills = m_Node_Domains & m_tvPathSep & m_Node_Skill

'Build the image list of small icons.
imlIcons.ListImages.Add , "Technician", LoadPicture("Technician.bmp")
imlIcons.ListImages.Add , "Location", LoadPicture("Location.bmp")
. . .
tv_ComponentTree.ImageList = imlIcons
lv_ContentsList.SmallIcons = imlIcons

'Build the image list of icons.
imlIcons.ListImages.Add _
        Key:=m_Node_Technician, _
        Picture:=LoadResPicture(icIDB_TECHNICIAN, vbResBitmap)
imlIcons.ListImages.Add _
        Key:=m_Node_location, _
        Picture:=LoadResPicture(icIDB_LOCATION, vbResBitmap)
imlIcons.ListImages.Add _
        Key:=m_Node_Priority, _
        Picture:=LoadResPicture(icIDB_PRIORITY, vbResBitmap)
. . .
imlBigIcons.ListImages.Add _
        Key:=m_Node_Priority, _
        Picture:=LoadResPicture(icIDB_PRIORITY, vbResBitmap)

'Attach the icons to visual components.
tv_ComponentTree.ImageList = imlIcons
lv_ContentsList.SmallIcons = imlIcons
lv_ContentsList.Icons = imlBigIcons

'Add Node objects.
sNodeKey = m_Node_Technician
tv_ComponentTree.Nodes.Add _
    Key:=sNodeKey, _
    Text:=m_Node_Technician, _
    Image:=m_Node_Technician

sNodeKey = m_Node_Domains
tv_ComponentTree.Nodes.Add _
    Key:=sNodeKey, _
    Text:=m_Node_Domains
tv_ComponentTree.Nodes.Add _
    relative:=sNodeKey, _
    relationship:=tvwChild, _
    Key:=sNodeKey & m_Node_location, _
    Text:=m_Node_location, _
    Image:=m_Node_location
. . .

The code to populate the Contents pane is almost as straightforward. For the sake of brevity, I will only show how the technician information is filled into the ListView control.

Examining the following code you can see how easy it is to populate the Contents pane. For a report view, simply add the initial column and all subsequent sub-items for that row. For a nonreport view, simply add the text and the icon for the record. Repeat this for each record in the collection.

Dim oItem As ListItem
Dim oDomainTechnician As CTech
Dim oLocation As CLocation
Dim oSkill As CSkill
Dim oDomainTechnicians As Collection

'Get the collection of technicians.
Set oDomainTechnicians = m_oTechAdmin.GetTechnicians

'Process each technician.
For Each oDomainTechnician In oDomainTechnicians
   If lv_ContentsList.View = lvwReport Then
      sMisc = oDomainTechnician.Alias
      Set oItem = lv_ContentsList.ListItems.Add( _
                     Key:=sMisc, _
                     Text:=sMisc, _
                     Icon:=m_Node_Technician, _
                     SmallIcon:=m_Node_Technician)
      Set oLocation = oTechAdmin.GetLocations.Item( _
                                    oSysAdmin.FmtPKId(oDomainTechnician.LocationId))
      oItem.SubItems(1) = oLocation.Desc
      Set oSkill = oTechAdmin.GetSkills.Item( _
      oSysAdmin.FmtPKId(oDomainTechnician.SkillId))
      oItem.SubItems(2) = oSkill.Desc
   Else
      lv_ContentsList.ListItems.Add _
         Key:=oDomainTechnician.Alias, _
         Text:=oDomainTechnician.Alias, _
         Icon:=m_Node_Technician, _
         SmallIcon:=m_Node_Technician
   End If
Next oDomainTechnician

Set oDomainTechnicians = Nothing

Displaying object properties

Once a component has been selected, its contents are displayed and can be manipulated. Each item in the Contents pane responds to a right mouse click that displays a relevant menu. For example, if the Technician component is selected, then right-clicking an item in the Contents pane will display a pop-up menu for changing the properties of that technician (Figure 3). Right-clicking in the Contents pane without any item selected displays a menu for adding to the selected Component.

Figure 3. The pop-up menu for items in the Contents pane

Responding to the right mouse click takes a bit more work than populating the Contents pane.

Pop-up menus

In order to display a right-click pop-up menu, the program needs to have a menu predefined. In the HDExplr application, I created a form called frmContext that only has a menu control on it. Each pop-up menu is given a unique name and it is this name that is used to differentiate the menus to be displayed on a right-click. The following code shows how to bring up a pop-up menu called mnu_lv_technician when the user right-clicks the Contents pane:

Private Sub lv_ContentsList_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
. . .
'Set form context variable to nothing selected
frmContext.Selected_Context = CM_NOTHING_SELECTED

'Bring up the appropriate submenu.
Select Case tv_ComponentTree.SelectedItem.FullPath
   . . .
   Case TV_TECHNICIANS_NODE
      PopupMenu frmContext. mnu_lv_Technician
   . . .
End Select
. . .

Once a menu selection is made, the relevant dialog box, showing existing properties, options, and so on, is displayed (Figure 4).

Figure 4. Clicking a command from a pop-up menu displays a modal dialog box

The following code displays a modal dialog box in response to a selection from the pop-up menu (the featured section displays the dialog box for updating the technician data):

'Respond to the user selection.
Select Case frmContext.Selected_Context
   'If adding a technician . . .
   Case CM_TECHNICIAN_ADD
      '. . . set empty parameters to force addition and show the form.
      frmTechMaint.SetParameters "", -1, -1, DM_ADD
      frmTechMaint.Show vbModal, Me

   'If modifying a technician . . .
   Case CM_TECHNICIAN_UPDATE
      '. . . get the selected technician object . . .
      Set oTech = m_oTechAdmin.GetTechByAlias(m_ItemClicked.Key)

      '. . . and set existing parameters to modify and show the form.
      frmTechMaint.SetParameters oTech.Alias, oTech.SkillId,
                                 oTech.LocationId, DM_UPDATE
      Set oTech = Nothing
      frmTechMaint.Show vbModal, Me
. . .
End Select
. . .
End Sub

Contents of the HDExplr Project

Table 3 lists the various files, and their descriptions, for the HDExplr project.

Table 3. The Files for the HDExplr Project

Name Type Description
frmAbout, frmSplsh, frmOpt, frmBrows Form Contains the code and form for the specific dialog
frmCntxt Form Contains the code and form for the various context menus used in the explorer panes of the main screen
frmDmMnt, frmSysPp, frmTchMnt Form Contains the code and form for the specific domain maintenance dialog
frmMain Form Contains the code and form for the explorer interface. This is the main form of the application.
basMain Module Contains the initialization code and the Sub Main for the project
res_h.bas Module Contains the constants that correspond to the IDs in the compiled .rc file (HDExplr.res)
HDExplr.res Resource compiled file Compiled resources
HDExplr.rc Resource plaintext file Contains the plaintext descriptions of the resources
Resource.h Header file for HDExplr.rc Contains constants for .rc file
MkHDxRes.* Project Microsoft Visual C++® project to be used to generate .res file from .rc file

Conclusion

As you can see from the article, the HelpDesk Explorer administration application can be used in various ways to manage and optimize the HelpDesk sample. I hope that you examine the sample code and see how easy it is to extend the HDExplr for your own additions to the HelpDesk sample, and also find it a useful example of how to write a Explorer-type application.

Appendix

Domain Deletion

Once a domain entry is added to the table, it is unlikely that the information would ever change. As such, HDExplr allows additions or modifications to the domain tables but not deletions. This is not to say that deletions can not be made, but the HelpDesk sample was designed with the assumption that "once entered, always entered." This philosophy extends to all of the data, including requests, and their related detail records, which are never deleted, but merely archived to history tables.

However, if a domain is accidentally deleted, or a domain entry must be deleted, the appendix at the end of this article explains the steps required either to restore the domain, or to adjust the other tables to reflect the domain entry adjustment.

When the HelpDesk sample was designed choices had to be made between storing the actual lookup keys in the request records and so on, or storing just the Primary Key Id (PKId) for a relevant record. While storing the lookup keys would have made the reverse engineering of a domain feasible should the domain be deleted, it is not localizable.

Storing the PKIds in the records made for a much more localizable application. The disadvantage of this was that the domain lookups via the PKId were now dependent on record sequencing, thus reconstructing a domain must be reproduced in the exact original record sequence.

How is this restoration accomplished? By restoring from the backup data set. (You are backing up your data, right?)

Domain Entry Deletion

In order to delete an entry once it has been used in a request would involve the following steps.

  1. Wait until all users are logged out of the HelpDesk application.

  2. Set the NoLoginsAllowed flag to TRUE. See the section on System setup for details on how this would be done.

  3. Delete the relevant entry from the domain table.

  4. Perform a global database update, replacing all occurrences of the deleted domain entry PKId with a more relevant one. This must be done in the historical data tables also.

  5. Set the NoLoginsAllowed flag to FALSE.