Visual Basic Clients for the HelpDesk Sample

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.

Introduction

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:

User Client

The user client application explained here allows a user to do the following:

Valid User

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

Browsing the Request List

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

Creating a New Request

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

Sending More Information about a Request

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

Details of a Request

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.

Sending Confirmation

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

Technician Client

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.

Log On

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

Browsing the Request List

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

Claiming Requests

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

Corresponding with the User

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.

Sending Standard Responses

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

Sending Nonstandard Responses

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

Sending Confirmation

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
...

Conclusion

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.