Venu Yerra
MSDN Content Development Group
November 1997
Updated:February 2, 1998
Click to copy the sample files for the HelpDesk Technician and User clients.
The HelpDesk sample is an extensible, automated user-support application. It can be customized to add extra features in order to deploy a technical support system in any organization.
HelpDesk uses different Microsoft technologies to build an automated solution. This sample consists of a set of clients, Component Object Model (COM) servers that encapsulate workflow, business logic, and a database at the back end. Figure 1 shows the HelpDesk system.
Figure 1. The HelpDesk system
This article explains two clients built for the HelpDesk sample using Microsoft® Visual Basic® version 5.0 with Service Pack 2:
The user client application explained here allows a user to do the following:
For the purposes of the HelpDesk sample, anyone who can log on to the corporate network is considered a valid user, with no separate log on required for the client application. When the application is started, the GetUserName Microsoft Win32® application programming interface (API) retrieves the user logon name. The following Visual Basic code declares the GetUserName function and retrieves the user name:
Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long
Private Function GetLoggedInUser(sUserName As String) As Boolean
Dim sBuff As String * 25
Dim lRet As Long
GetLoggedInUser = True
'Get the user name, remove NULLs, and trim trailing spaces.
lRet = GetUserName(sBuff, 25)
sUserName = Trim$(Left(sBuff, InStr(sBuff, Chr(CHAR_ZERO)) - 1))
'Return false if no name is returned.
If sUserName = vbNullString Then
GetLoggedInUser = False
End If
End Function
Figure 2 shows the User Request List form—the initial form displayed when the user client is run. It contains a list of all requests created by the user, including the Tracking Number, Description, Status, Request Date, and Skills Required for each request.
Figure 2. The user client Request List
The Load event of the User Request List form creates a new instance of a CUser object and assigns it to a module level variable, m_oUser. The logged on user name is assigned to the Alias attribute of the user object:
'Create a new instance of a module level User object.
Set m_oUser = g_oAdmin.GetNewUser()
'Assign a username to the module level User object.
m_oUser.Alias = g_sEAlias
The Requests collection, a property of the CUser object, contains a list of all requests made by the user. The following code demonstrates how to fill the Requests collection in the ListView:
Private Sub FillListView()
Dim oReq As HDClient.CRequest
...
'Clear the old request items.
lvwDB.ListItems.Clear
'Get the count of requests in the User object.
lCount1 = m_oUser.Requests.Count
'Set the min and max properties of the progress bar.
If lCount1 > 0 Then
pgbReqLst.Visible = True
pgbReqLst.Min = 0
pgbReqLst.Max = lCount1
Else
Exit Sub
End If
'Get the relevant collections.
Set cStatus = g_oAdmin.GetReqStatus()
Set cSkills = g_oAdmin.GetSkills()
'Fill in the ListView with the requests and their details.
For Each oReq In m_oUser.Requests
GetIconForStatus cStatus, oReq.StatusId, sTemp, sLIcon, sSIcon
Set oItem = lvwDB.ListItems.Add(, , oReq.TrackingNo, sLIcon, sSIcon)
oItem.SubItems(1) = oReq.Desc
...
GetSkillDesc cSkills, oReq.SkillId, sTemp
oItem.SubItems(4) = sTemp
lCount = lCount + 1
pgbReqLst.Value = lCount
Next
'Reset the progress bar
pgbReqLst.Value = pgbReqLst.Min
pgbReqLst.Visible = False
...
End Sub
Figure 3 shows the Create a New Request form, which is used to create a new request. This form can be invoked by clicking the New toolbar button or by clicking New from the File menu.
Figure 3. Creating a new request
This form allows input of all details required for creating a request: the location and skills required are used to assign an appropriate technician; the priority indicates the importance of the request; and the description lets the technician understand the problem.
To create a new request, the Click event of the Send button calls the InsertRequest method of the Admin object:
Private Sub cmdSend_Click()
Dim oReq As HDClient.CRequest
'Validate the location.
If (cmbLoc.ListIndex < 0) Then
MsgBox ERR_NOLOCATION
cmbLoc.SetFocus
Exit Sub
End If
'Validate the priority.
...
'Get a new Request object.
Set oReq = g_oAdmin.GetNewReq()
'Set who requested; user alias is in a global variable
oReq.Alias = g_sEAlias
oReq.Desc = Trim$(txtReq) 'Sets the Description attribute.
oReq.LocId = cmbLoc.ItemData(cmbLoc.ListIndex)
oReq.SkillId = cmbSkill.ItemData(cmbSkill.ListIndex)
oReq.PriorityId = cmbPriority.ItemData(cmbPriority.ListIndex)
'Insert the request.
If Not g_oAdmin.InsertRequest(oReq) Then
MsgBox ERR_INSERTFAILED 'Display an error message if the function fails.
End If
Set oReq = Nothing 'Clear the object.
End Sub
If the initial user-provided request description is insufficient for the technician to resolve the request, the Send Text Request form allows a user to send additional information to the technician.
The information entered in the textbox is sent using the SendTextRequest method of Admin object, called by the Click event of the Send button:
Private Sub cmdSend_Click()
Dim oReqDet As HDClient.CReqDetail
Dim oReq As HDClient.CRequest
If Trim$(txtReq) = vbNullString Then
MsgBox ERR_NOREQTEXT
Exit Sub
End If
'Get a new Request Detail object.
Set oReqDet = g_oAdmin.GetNewReqDet()
Set oReq = g_oAdmin.GetNewReq()
'Set the attributes for the Request object.
oReq.Alias = g_sEAlias
oReq.TrackingNo = m_lTrackID
'Set the attributes for the Request Detail object.
oReqDet.DetailText = Trim$(txtReq) 'Text of request
'Send a text response.
If Not (g_oAdmin.SendTextRequest(oReq, oReqDet)) Then
MsgBox ERR_SENDREQTEXT
End If
'Clear the objects.
Set oReq = Nothing
Set oReqDet = Nothing
'Unload the form after sending text request.
Unload Me
End Sub
The correspondence between user and technician continues until the request is resolved. The Request Details form displays all correspondence between the user and technician about a request.
Once a technician resolves a request, the user must confirm the resolution. This is done via Request Resolved on the File menu of the User Request List form. The following code sends the confirmation:
Dim oReq As HDClient.CRequest
'Exit if there is no selected item in the ListView.
If lvwDB.SelectedItem.Text = vbNullString Then
Exit Sub
End If
'Get a new instance of the Request object.
Set oReq = g_oAdmin.GetNewReq()
'Set the attributes for request object
oReq.TrackingNo = CLng(lvwDB.SelectedItem.Text)
oReq.Alias = g_sEAlias
'Send the confirmation.
If Not g_oAdmin.SendConfirmation(oReq) Then
MsgBox ERR_CONFNOTSENT
End If
Set oReq = Nothing
Technical personnel assigned to resolve requests in the HelpDesk system use the technician client. The following requirements provide the basis for the design of the technician-client user interface. The technician client must allow the technician to do the following:
Let's see now how these are implemented.
A valid technician is one who has been registered in the HelpDesk system as a technician. The following code in the Load event of the Technician Request List form checks for a valid technician:
'Create an Admin object.
Set g_oAdmin = New HDClient.CAdmin
'Initialize the Admin object so that it displays the requests and
'request details for the technician.
If g_oAdmin.Init(m_sTechAlias, TECH_LOGGEDIN) Then
'Create a Technician object.
Set m_oTech = m_oAdm.GetTechByAlias(m_sTechAlias)
Else
Set m_oTech = Nothing
MsgBox ERR_TECHNOTFOUND
Unload Me
End If
Figure 4 shows the Technician Request List form, which is the initial form displayed when the technician client is run. This form displays a list of all requests assigned to a technician, and includes the tracking number, status, description, priority, date requested, and location for each request. The code that fills the list with requests is similar to what we have seen in the user client.
Figure 4. Request List in the technician client
Unclaimed requests are continuously reshuffled by the HelpDesk system, so those requests can be reassigned to more available or more appropriate technicians. A Refresh button updates the Request List so that the technician views the most current data. The following code shows how the refresh is implemented. The module-level technician object is reinitialized, the GetTechByAlias method of the Admin object retrieves current data and displays the attributes of the Technician object, and the FillListView procedure fills the data in the list:
Private Sub cmdRefresh_Click()
'Terminate the Technician object.
if m_oTech is not nothing then
m_oTech.Term
Set m_oTech = Nothing
Endif
Set m_oTech = g_oAdmin.GetTechByAlias(m_sTechAlias)
FillListView
End Sub
Once the technician reviews the list of requests, he or she can choose which assigned request to work on. Hence, the status of an initially assigned request is "Assigned not claimed." The technician claims an assigned request in order to work on it. To claim a request, the Click event of the Claim toolbar button calls the ClaimRequest method of the Admin object.
Dim oReq As HDClient.CRequest
Dim oTech As HDClient.CTech
Dim lReqId As Long
'Create a Technician object.
Set oTech = g_oAdmin.GetNewTech()
'Set the Id for the Technician object.
oTech.PKId = m_oTech.PKId
'Create a new Request object.
Set oReq = g_oAdmin.GetNewReq()
'Get the selected request from the ListView.
If (lvwDB.ListItems.Count <> 0) Then
lReqId = CLng(lvwDB.SelectedItem.Text)
Else
Exit Sub
End If
'Set the Id for the Request object.
oReq.PKId = lReqId
'Claim the request.
If Not (g_oAdmin.ClaimRequest(oReq, oTech)) Then
MsgBox ERR_CLAIMFAILED
End If
'Clear the Technician and Request objects.
Set oReq = Nothing
Set oTech = Nothing
'Refresh the data and fill the ListView.
cmdRefresh_Click
A technician can release a claimed request, which resets the request status to "Unclaimed." The Click event of the Unclaim toolbar button calls the UnclaimRequest method of the Admin object to release a request, as follows:
Dim oReq As HDClient.CRequest
Dim oTech As HDClient.CTech
Dim lReqId As Long
Set oReq = g_oAdmin.GetNewReq()
Set oTech = g_oAdmin.GetNewTech()
'Set the Id for the Technician object.
oTech.PKId = m_oTech.PKId
'Get the selected request from the ListView.
If (lvwDB.ListItems.Count <> 0) Then
lReqId = lvwDB.SelectedItem.Text
Else
Exit Sub
End If
'Set ReqId to the Request object.
oReq.PKId = lReqId
'Unclaim the request.
If Not (g_oAdmin.UnclaimRequest(oReq, oTech)) Then
MsgBox ERR_UNCLAIMFAILED
End If
'Clear the objects.
Set oReq = Nothing
Set oTech = Nothing
'Refresh the data and fill in the combo box.
cmdRefresh_Click
The technician needs to notify the HelpDesk system when starting to work on a claimed request. The Click event of the Commence toolbar button calls the WorkRequest method of Admin object:
Dim oReq As HDClient.CRequest
Dim oTech As HDClient.CTech
Dim lReqId As Long
'Create a Technician object.
Set oTech = g_oAdmin.GetNewTech()
'Set the Id for the Technician object.
oTech.PKId = m_oTech.PKId
'Create a new Request object.
Set oReq = g_oAdmin.GetNewReq()
'Get the selected request from the ListView.
If (lvwDB.ListItems.Count <> 0) Then
lReqId = CLng(lvwDB.SelectedItem.Text)
Else
Exit Sub
End If
'Set the Id for the Request object.
oReq.PKId = lReqId
'Start working on the request.
If Not (g_oAdmin.WorkRequest(oReq, oTech)) Then
MsgBox ERR_COMMENCEFAILED
End If
'Clear the Technician and Request objects.
Set oReq = Nothing
Set oTech = Nothing
'Refresh the data and fill in the combo box.
cmdRefresh_Click
In the request resolution cycle, there may be more than one instance when the technician has to respond to the user about a request and vice versa. The Request Details form chronologically displays the correspondence details between the technician and the user.
Technicians can respond to user requests with standard as well as customized responses. The standard text and voice responses are stored in the HelpDesk system and are available from the Standard Responses form.
The Standard Responses form can send a standard text response or a standard voice response. To send a standard text response, the SendStdTextResponse method of the Admin object is called. To send a standard voice response, the SendSVoiceResponse method of the Admin object is called. The following code in the Click event of the Send button sends the standard responses:
Private Sub cmdSend_Click()
Dim oReqDet As HDClient.CReqDetail
Dim bTemp As Boolean
'Check for selected items.
If lstStdResp.Text = vbNullString Then
Exit Sub
End If
'Set the attributes of the Request Detail object.
oReqDet.DetailText = txtStd
oReqDet.DetTypeId = 0
oReqDet.Request = m_lTrackID
'Send a response.
Select Case m_lRespType
Case icText
bTemp = g_oAdmin.SendStdTxtResponse(oReqDet)
Case icVoice
bTemp = g_oAdmin.SendSVoiceResponse(oReqDet)
End Select
'Unload the form.
Unload Me
End Sub
If an appropriate standard response is not available, the technician may choose to compose a response to the user. The technician enters the response text in the Text Response form. To send the response text, the Click event of the Send button calls the SendTextResponse method on the Admin object.
Private Sub cmdSend_Click()
Dim oReqDet As HDClient.CReqDetail
If Trim$(txtResp) = vbNullString Then
MsgBox ERR_NORESPTEXT
GoTo ExitLoop
End If
'Get a new Request Detail object.
Set oReqDet = g_oAdmin.GetNewReqDet()
'Set attributes for Request Detail object.
oReqDet.DetailText = Trim$(txtResp)
'GetRequestId from Track ID.
oReqDet.Request = m_lTrackID
oReqDet.TechId = g_lTechId
'Send a text response.
If Not (g_oAdmin.SendTxtResponse(oReqDet)) Then
MsgBox ERR_SENDRESPTEXT
End If
Set oReqDet = Nothing
End Sub
When a request is resolved, the technician notifies the HelpDesk system. The Click event of the Resolve toolbar button calls the ResolveRequest method of the Admin object:
Dim oReq As HDClient.CRequest
Dim oTech As HDClient.CTech
Dim lReqId As Long
Set oReq = g_oAdmin.GetNewReq()
Set oTech = g_oAdmin.GetNewTech
'Set the Id for the Technician object.
oTech.PKId = m_oTech.PKId
'Get the selected request from the ListView.
If (lvwDB.ListItems.Count <> 0) Then
lReqId = lvwDB.SelectedItem.Text
Else
Exit Sub
End If
'Set ReqId to the Request object.
oReq.PKId = lReqId
If Not g_oAdmin.ResolveRequest(oReq, oTech) Then
MsgBox ERR_RESOLVEFAILED
End If
Set oReq = Nothing
Set oTech = Nothing
'Refresh the data and fill in the combo box.
cmdRefresh_Click
...
As you can see, the HelpDesk COM object model is used extensively in developing the Visual Basic clients. Because the object model is encapsulated and extensible, adding further functionality to the clients is easy.
If you look at the clients closely, you will see some common functionality between the two. An alternate approach to designing the clients would be to encapsulate common functionality into a reusable ActiveX control. For example, the user browses all his or her created requests, and the technician browses all his or her assigned requests. The user interface remains similar but the data retrieval process differs. An ActiveX™ control can be developed to fill the request list using a specific property that, when set to the appropriate client, populates the request list accordingly. The advantage of this implementation is that the whole functionality of filling the request list can be encapsulated. Also, changes to the ActiveX control do not affect the client as long as the existing properties, methods, and events are not changed.
Designing ActiveX controls for code reuse and encapsulation is neatly documented in "Creating ActiveX Components" in the Visual Basic documentation. See also, "The Corporate Benefits Sample ChartVB3D ActiveX Control," by Ken Bergmann and James Braum in the MSDN™ Library.