Programming Microsoft Outlook and Microsoft Exchange, Second Edition (DV-MPS Programming)

To convert the Expense Report application from Chapter 12 to a routing application, a few major changes were made to create a routing map, update the ASP pages so that they send e-mail messages to the expense routing folder rather than update the status of the expense items directly, and implement some custom script actions. Before looking at the changes to the ASP pages and script, you need to set up the Expense Routing application.

Setting Up the Expense Routing Application

Before you can install the application, you must have a Windows NT 4.0 Server and a client with certain software installed. Table 13-7 describes the installation requirements.

Table 13-7 Installation Requirements for the Expense Routing Application

Required Software Installation Notes
Exchange Server 5.5 SP1 with Outlook Web Access Exchange Server 5.5 SP1 installs the routing engine and routing objects.
IIS 3.0 or higher with Active Server Pages IIS 4.0 is recommended.
CDO library (cdo.dll)

CDO Rendering library (cdohtml.dll)

Exchange Server 5.5 SP1 installs CDO library 1.21 and CDO Rendering library 1.21. Outlook 98 installs CDO library 1.21.
For the client:

A web browser

Outlook 98

Visual Basic 6.0

For the web browser, Internet Explorer 4.0 recommended. You can run the client software on the same machine or on a separate machine.

To install the Expense Routing application, copy the Expense Routing folder from the companion CD to your web server where you want to run the application. Start the IIS administration program. Create a virtual directory that points to the location where you copied the expense routing files, and name the virtual directory expenserouting. Make sure you enable the Execute permissions option for the virtual directory. You will be able to use the following URL to access your Expense Routing application: http://yourservername/expenserouting.

Open the Exchange Administrator program. Open the Properties dialog box for the Folders\System Folders\Events Root\EventConfig_servername folder. Click the Client Permissions button, add a user who will administer the Expense Routing folder, and grant the user Author permissions. Click OK twice.

Launch Outlook using the user you selected to administer the folder Expense Routing. Create a new public folder named Expense Routing under All Public Folders. Next, verify that the Server Scripting add-in is installed. By default, Outlook 98 does not install the Server Scripting add-in. To install the Server Scripting add-in, select Options from the Tools menu, click on the Other tab, click Advanced Options, and then click Add-In Manager. Check the Server Scripting check box in the Add-In Manager dialog box. In the Exchange Administrator program, open the Properties dialog box for the Expense Routing public folder. Click on the Advanced tab, uncheck the Hide From Address Book check box, and click OK.

Start the Registry Editor on your server, and open this key:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MSExchangeES\ Parameters

Set Logging Level DWORD to 5, to log the maximum amount of information.

NOTE


Be sure to set Logging Level to 0 when you are finished testing the Expense Routing application. If you do not, your Application log will be quickly filled up with MSExchangeES logging entries.

Next, you will create a default map using the Exchange Routing Wizard. To install the Routing Wizard on your client machine, run Rwsetup.exe from the Exchange Server 5.5 Service Pack 1 CD. For Windows 95 and Windows 98, the location for Rwsetup.exe is \Eng\Server\Support\Collab\Sampler\Routing\Win95. For Windows NT, the location is \Eng\Server\Support\Collab\Sampler\ Routing\Winnt\i386. You must have Outlook 98 installed on the machine where you are installing the Routing Wizard.

After you have installed the Routing Wizard, run it by selecting it from the Programs menu. The Routing Wizard requires you to log on to Exchange Server. Use the account that you used to create the Expense Routing public folder. In the Step 1 screen, choose the Expense Routing public folder as shown in Figure 13-5. Step through the remaining screens of the wizard. Add recipients when necessary. Since the Routing Wizard is being used only to create a default map, which we will modify later, the remaining settings in the wizard are not important.

Locate the RoutingAgentScript.txt file included with the expense routing files. Be sure the read-only flag for the file is unchecked and open it in Notepad. Perform a search in the code and replace all instances of the text localhost with the name of your web server. Save and close Notepad.

Run the updated Agent Install program in the Agent Install Updated folder on the companion CD. Log into your Exchange Server using the account you used to create the Expense Routing public folder. Select the Expense Routing public folder, as shown in Figure 13-6.

Figure 13-5 Selecting the Expense Routing public folder to install a default routing map.

Figure 13-6 Selecting the Expense Routing public folder in the updated Agent Install program. The agent and map contained in the Expense Routing folder were added using the Routing Wizard.

Click the Delete This Agent button, and then click OK to delete the agent in the Expense Routing public folder generated by the Routing Wizard. Click No when asked to delete the routing map. Click the Add New Agent button, click Yes when asked to create a routing agent, and then click OK to select a script. In the Select Script dialog box, shown in Figure 13-7, select the RoutingAgentScript.txt file that you modified earlier, and click OK.

Figure 13-7 Selecting the script for the Expense Routing agent.

In the main interface for the updated Agent Install program, click the View Default Map button. Click the Delete All Rows button to clear the map. Use the Delete Column button to delete all parameter columns except Parameter1. Click the Select Script button. When asked if you want to use the default script in the folder, click Yes. Check the Parse Script For Functions check box, and click OK after the program tells you how many new functions were added from the script. Enter the map instructions shown in Figure 13-8. Double-click or press the Enter key to edit a cell, and use the Add Row button to add rows. You will be able to select intrinsic and custom actions from a combo box that displays in the Action column. When finished, click Save, and then click Exit.

To test the Expense Routing application, use the following URL to submit expense reports: http://yourservername/expenserouting. The application is used in the same way as the Expense Report application in Chapter 12. Figure 13-9 shows the Expense Report Status Page with some sample expense reports in different routing states. To see sample expense reports, open the Expense Routing.pst file included with the expense routing files in Outlook.

NOTE


If the application does not work as expected, check that you have Service Pack 1 of Exchange Server installed. Also, check the Application log of the Event Viewer for any logged errors.

Figure 13-8 The routing map for the Expense Routing agent.

Figure 13-9 The status page for the Expense Routing application, where expense reports are in different routing states.

Changes to the ASP Section of the Application

The biggest changes to the ASP section of the application occurred in the approval and rejection code for an expense report. The expense approval and rejection code had to be changed so that it did not update the item directly with the approval or the rejection of the expense report. Instead, the code was modified so that it sent e-mail to the requesting user with the response of the expense approver, regardless of whether this response was an approval or rejection. To implement this functionality, the code creates an e-mail message, and it adds a subject containing the string APPWF for approval and REJWF for rejection, as well as the RUI number for the process instance that this approval or rejection is for. The application appends RUI=number to the end of the subject.

To retrieve the RUI number on an approval or rejection in the ASP application, the custom script action that sends the message to the manager for approval has to pass the RUI number to the ASP application. To do this, as you will see, the custom script action calls into the Routing Object library and uses a specific property contained on the ProcInstance object, named RUI.

Once the ASP application has all the necessary information, it can create a fully formed approval or rejection message with the RUI number and mail this to the Expense Routing public folder. The next code segment, from finalapprove.asp, shows creating the approval or rejection message and sending it to the folder. The code used to implement the Expense Report application in Chapter 12 is commented out in the listing so that you can compare the two implementations.

<!--#include file="logon.inc"--> <% Dim oMessage Dim AMSession CheckAMSession BAuthenticateUser Set AMSession= Session( "AMSession") if AMSession Is Nothing Then ' CheckSession was unable to retrieve or create a session Response.Write( "GetAMSession returned nothing!<br>") End If Mailbox = Session("Mailbox") set objFolder = Session("objFolder") if objFolder is Nothing then Response.Write( _ "Cannot access the Expense Report folder!<br>") end if objInfoStoreID = Session("objInfoStoreID") 'Get the entry ID for the message from the query string objMessageID = Session("Entryid") 'Get the message by its ID set oMessage = AMSession.GetMessage(objMessageID, objInfoStoreID) 'Get the Fields of the report set Total = oMessage.Fields("Total") 'Get the user who posted the message set addentry = oMessage.Sender set UsersManager = addentry.Manager Approver = Session("Approver") set newExpenseReport = AMSession.outbox.messages.add set mynewrecipient = newExpenseReport.recipients.add 'Need to change this to a different folder if it is different mynewrecipient.Name = "Expense Routing" mynewrecipient.resolve lRUI = Session("RUI") if Request.Form("Approve") = "Approve" then newExpenseReport.subject = "APPWF:,RUI=" & Cstr(lRUI) 'newExpenseReport.text = Approver & _ '" has approved the expense report. " & _ '"The total value of this report was " & Total newExpenseReport.send 'oMessage.Fields("StatusInt") = 3 'Approved 'oMessage.Fields("Status") = "Approved by " & Approver 'oMessage.Fields("Approver") = Approver currentstatus = 3 else newExpenseReport.subject = "REJWF:,RUI=" & Cstr(lRUI) 'newExpenseReport.text = Approver & _ '" has rejected the expense report. " & _ '"The total value of this report was " & Total newExpenseReport.send 'oMessage.Fields("StatusInt") = 4 'Rejected 'oMessage.Fields("Status") = "Rejected by " & Approver 'oMessage.Fields("Approver") = Approver currentstatus = 4 end if 'oMessage.Update TRUE, TRUE %> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <% if currentstatus = 3 then %> <title>Expense Report Approved Page</title> <% else %> <title>Expense Report Rejected Page</title> <% end if %> </head> <body bgcolor="#FFFFFF"> <p><font size="2" face="Arial Black"> <% if currentstatus = 3 then %> Routing Final Approval to <%=addentry.Name%></font></p> <hr> <font size="2" face="Arial Black"> The following funds have been successfully transferred: <p align="center">$<%=oMessage.Fields("Total")%></Font></p> <% else %> Routing Rejection message to <%=addentry.Name%></font></p> <hr> <% end if %> </body> </html>

Changes to the Server Script

Whereas the changes to the ASP application were very minor, the changes to the server-side script that runs on the Exchange Server were somewhat more extensive. The first change was to turn the scripting agent script into a routing agent script. We did this by modifying the primary subroutine names so that they had the Route_ naming convention rather than the scripting agent convention. The script also had to be updated so that Boolean values were returned by some of the subroutines. This was necessary to implement branching using OrSplits in the routing map.

The script also needed functionality to update the status of the expense report when an approval or rejection message is received in the folder—functionality originally implemented in the ASP application. The status is defined as custom properties on the message.

The following is the updated script code, RoutingAgentScript.txt, that turns the Expense Report application into a routing application:

<SCRIPT RunAt=Server Language=VBScript> '-------------------------------------------------------------------- 'FILE DESCRIPTION: Expense Report Sample Script for routing objects ' '-------------------------------------------------------------------- '------------------------------------------------------------------ ' Localized strings '-------------------------------------------------------------------- ' Put all localizable strings and constants here '-------------------------------------------------------------------- ' Global Variables '-------------------------------------------------------------------- Dim AMSession Dim fldrOutbox Dim msgTarget Dim fldrTarget Dim ExpRentalCar Dim ExpAirfare Dim ExpHotel Dim ExpMeals Dim ExpTotal Dim g_oMsgIn 'Incoming Message Object Dim g_oProcInstance 'Process Instance Dim g_oPIMsg 'Process Instance Message Object Dim g_oSession 'Session Object Dim g_oFolder 'Routing Folder Object Dim g_oAgentAddEntry 'Address Entry Object used for Inbox mailings '-------------------------------------------------------------------- ' Route Subs '-------------------------------------------------------------------- ' DESCRIPTION: Check the total of the expense report, and if it 'is under a specific amount, automatically approve the expense report Sub Route_CheckTotal(boolSuccess) Dim msgResponse Dim iMsgCount Dim msgManager Dim UsersManager Dim currentuser Dim currentapprover On Error Resume Next If InitializeObjects Then WriteToLog 1,"Message Count Succeeded" set ExpTotal = msgTarget.Fields.Item("Total") Set msgResponse = fldrOutbox.Messages.Add 'Get the RUI lRUI = g_oProcInstance.RUI 'Modify this line to change Expense Amount If ExpTotal > 5000 then WriteToLog 1,"Greater than max expense amount" msgResponse.Subject = "The Total was " & ExpTotal 'Message to manager set msgManager = fldrOutbox.Messages.Add set currentuser = msgTarget.Sender set UsersManager = currentuser.Manager currentapprover = UsersManager.Name msgResponse.Text = "This Expense Report has " & _ "been routed to your Manager: " & currentapprover 'Get the spaces out currentapprover = Replace(currentapprover," ","+") msgManager.Subject = _ "Approval Required for Expense Report!" 'Need to change this for your server and directory msgManager.Text = currentuser.name & _ " has submitted an expense report for " & _ ExpTotal & ". Please review it at http://" & _ localhost/expenserouting/approve.asp?entryid=" & _ msgTarget.ID & "&Approver=" & CurrentApprover & _ "&RUI=" & Cstr(lRUI) msgManager.Recipients.Add "","",1,UsersManager.ID msgManager.Recipients.Resolve(False) msgManager.Send msgTarget.Fields("strStatus") = "Awaiting " & _ "Approval from " & UsersManager.Name msgTarget.Fields("StatusInt") = 2 msgTarget.Fields.Add "Approver",8,UsersManager.Name msgTarget.Update Else 'Expense Report <= Max Amount WriteToLog 0,"Less than max expense amount" msgResponse.Subject = _ "This Expense Report has been Approved" msgResponse.Text = "Your expense report for " & _ ExpTotal & " has been automatically approved." & _ "Funds are being transferred!" msgTarget.Fields("strStatus") = "Approved " & _ "automatically and routed for payment" msgTarget.Fields("StatusInt") = 3 msgTarget.Update boolSuccess = True End If If Err.Number = 0 Then msgResponse.Recipients.Add "", "", 1, _ msgTarget.Sender.ID If Err.Number = 0 Then msgResponse.Recipients.Resolve(False) If msgResponse.Recipients.Resolved = True Then msgResponse.Send If Not Err.Number = 0 Then WriteToLog 0, _ "Message.Send Failed: " & _ Err.Description End If Else WriteToLog 0, _ "Recipients.Resolve Failed: " & _ Err.Description End If Else WriteToLog 0,"Recipients.Add Failed: " & _ Err.Description End If Else WriteToLog 0,"Messages.Add Failed: " & _ Err.Description End If Else WriteToLog 0,"InitializeObjects Failed: " & _ Err.Description End If ReleaseGlobalObjects End Sub Sub Route_IsTimeout(boolSuccess) On Error Resume Next Dim boolRes 'Boolean Result WriteToLog 0, "Starting IsTimeout" boolRes = InitializeObjects If Not boolRes Then WriteToLog 0, "InitializeObjects Failed" Else boolSuccess = g_oProcInstance.Timeout Set g_oProcInstance = Nothing End If WriteToLog "IsTimeout returns " & boolSuccess ReleaseGlobalObjects End Sub Sub Route_RouteToNextManager() On Error Resume Next Dim boolRes 'Boolean Result WriteToLog 0, "Starting RouteToNextManager" boolRes = InitializeObjects If Not boolRes Then WriteToLog 0, "InitializeObjects Failed" Else 'Get the RUI lRUI = g_oProcInstance.RUI 'Clear errors Err.Clear WriteToLog 0,"Rerouting beginning" set ExpTotal = msgTarget.Fields("Total") WriteToLog 0,"The Total is: " & ExpTotal 'Reroute the message set CurrentApprover = msgTarget.Fields("Approver") WriteToLog 0,"The current approver is: " & CurrentApprover set msgResponse = AMSession.Outbox.Messages.Add 'Create the recipient Set objonerecip = msgResponse.Recipients.Add objonerecip.Name = CurrentApprover 'Resolve the name against the Exchange Server 'directory objonerecip.Resolve 'Get the address entry so that we can pull out template 'info Set myaddentry = objonerecip.AddressEntry 'Get the manager from the addentry set NextApprover = myaddentry.Manager if NextApprover = Empty then 'We dont have a manager! 'Send a message to the current user set currentuser = msgTarget.Sender msgResponse.Subject = "No more manager to route to" msgResponse.Text = currentuser.name & _ " has submitted an expense report for " & ExpTotal & ". There are no other managers " & _ "to route to!" msgResponse.Recipients.Add "", "", 1, _ msgTarget.Sender.ID msgResponse.Send 'Resend a message to the current approver Set msgResendtoApprover = _ AMSession.Outbox.Messages.Add CurrentApproverName = _ Replace(CurrentApprover," ","+") msgResendtoApprover.Subject = _ "Repeat notice for Approval of an Expense Report!" msgResendtoApprover.Text = currentuser.name & _ " has submitted an expense report for " & ExpTotal & _ ". Please review it at http://localhost/" & _ "expenserouting/approve.asp?entryid=" & _ msgTarget.ID & "&Approver=" & CurrentApproverName & _ "&RUI=" & Cstr(lRUI) 'Create the recipient set oRecip = msgResendtoApprover.Recipients.Add oRecip.Name = CurrentApprover oRecip.Resolve msgResendtoApprover.Send WriteToLog 0,"No More Managers beyond " & _ CurrentApprover & " for this user." else NextApproverName = NextApprover.Name tmpNextApproverName = NextApprover.Name 'Got the next approver. Send a message to previous 'approver and user and reroute. set currentuser = msgTarget.Sender msgResponse.Subject = _ "An Expense Report has been rerouted" msgResponse.Text = currentuser.name & _ " has submitted an expense report for " & ExpTotal & _ ". It was rerouted because the 1 hour approval " & _ "time limit has expired. It is now routed to " & _ NextApproverName msgResponse.Recipients.Add "", "", 1, _ msgTarget.Sender.ID msgResponse.Send if err.number = 0 then WriteToLog 0,"Successfully rerouted" end if 'Now change the status and reroute to new person WriteToLog 0, "Updating fields on Message" msgTarget.Fields("strStatus") = "Rerouted and " & _ "awaiting Approval from " & NextApproverName msgTarget.Fields("Approver") = NextApproverName msgTarget.Update 'Now send a message WriteToLog 0, "Creating message to next " & _ "approver: " & NextApproverName Set msgNewApprover = AMSession.Outbox.Messages.Add WriteToLog 0, "Added message to outbox" 'Create the recipient 'Get the spaces out NextApproverName = Replace(NextApproverName," ","+") WriteToLog 0, "Got the spaces out of the name" msgNewApprover.Subject = _ "Approval Required for Rerouted Expense Report!" WriteToLog 0, "Added Subject" msgNewApprover.Text = currentuser.name & _ " has submitted an expense report for " & ExpTotal & _ ". Please review it at http://localhost/" & _ "expenserouting/approve.asp?entryid=" & _ msgTarget.ID & "&Approver=" & NextApproverName & _ "&RUI=" & Cstr(lRUI) WriteToLog 0, "Added Text" Set tmpRecip = msgNewApprover.Recipients.Add tmpRecip.Name = tmpNextApproverName WriteToLog 0, "Added Recipient" msgNewApprover.Recipients.Resolve WriteToLog 0, "Resolved Address" msgNewApprover.Send end if 'Manager! end if WriteToLog 0,"RouteToNextManager is done." ReleaseGlobalObjects End Sub Sub Route_UpdateStatus(boolApproved) On Error Resume Next WriteToLog 0, "Starting UpdateStatus with value: " & _ boolApproved boolRes = InitializeObjects If Not boolRes Then WriteToLog 0, "InitializeObjects Failed" Else 'Check to see if approved or rejected, update the 'status of the message, and send an e-mail Approver = g_oMsgIn.Sender WriteToLog 0, "Approver: " & Approver set newExpenseReport = AMSession.outbox.messages.add set mynewrecipient = newExpenseReport.recipients.add mynewrecipient.Name = msgTarget.Sender 'Original Sender mynewrecipient.resolve Total = msgTarget.Fields("Total") if boolApproved then 'Approved WriteToLog 0, "Sending approve message because " & _ "boolApproved is " & boolApproved msgTarget.Fields("strStatus") = "Approved by " & _ Approver msgTarget.Fields("StatusInt") = 3 msgTarget.Fields("Approver") = Approver newExpenseReport.subject = "Your expense " & _ "report has been Approved!" newExpenseReport.text = Approver & _ " has approved the expense report. The total " & _ "value of this report was " & Total newExpenseReport.send WriteToLog 0, "Sent Approval Message" else 'Rejected WriteToLog 0, "Sending reject message because " & _ "boolApproved is " & boolApproved msgTarget.Fields("strStatus") = "Rejected by " & _ Approver msgTarget.Fields("StatusInt") = 4 msgTarget.Fields("Approver") = Approver newExpenseReport.subject = "Your expense " & _ "report has been Rejected!" newExpenseReport.text = Approver & " has " & _ "rejected the expense report. The total " & _ "value of this report was " & Total newExpenseReport.send WriteToLog 0, "Sent Rejection Message" end if msgTarget.Update TRUE, TRUE WriteToLog 0, "Updated Message Status" end if ReleaseGlobalObjects end sub Sub Route_ReceivedApprovalMsg(boolSuccess) On Error Resume Next Dim varRet 'Variant return value Dim boolRes 'Boolean result Dim oRecipientEntry 'VoteTable recipient entry object Dim bstrUSubject 'Uppercased subject from incoming msg WriteToLog 0, "Starting ReceivedApprovalMsg" boolRes = InitializeObjects If Not boolRes Then WriteToLog 0, "InitializeObjects Failed" Else 'Notes: Outlook approval/reject buttons place the string ' Approve:" on the subject line, the URL version ' places APPWF: on the subject line. ' Check the subject line to find out if ' it's an Outlook message or a non-Outlook message. 'In expense routing sample, assume it will always be 'a non-Outlook message bstrUSubject = UCase(g_oMsgIn.subject) 'Look for APPROVE in subject If InStr(1, UCase(g_oMsgIn.subject), "APPWF") Then WriteToLog 0, "Message Approval Found." boolSuccess = True 'Otherwise look for REJECT in subject ElseIf InStr(1, UCase(g_oMsgIn.subject), "REJWF") Then WriteToLog 0,"Message Reject Found." boolSuccess = False End If end if ReleaseGlobalObjects WriteToLog 0, "ReceivedApprovalMsg Exit returned " & _ boolSuccess end sub '-------------------------------------------------------------------- ' Support Functions '-------------------------------------------------------------------- 'Description: WriteToLog Private Sub WriteToLog(boolRecordName,strMessage) Dim strResponse strResponse = Now & vbTab & strMessage & ":" if boolRecordName = 1 then strResponse = strResponse & " " & msgTarget.Subject else strResponse = strResponse & " " end if Script.Response = Script.Response & vbNewLine & strResponse end Sub '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' Name: InitializeObjects ' Area: Utility ' Desc: Set Message, Folder, and other globals. ' Check store that agent is operating in. ' Parm: None ' Retn: Boolean Success '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Private Function InitializeObjects() On Error Resume Next Dim bstrTemp Dim oStores 'InfoStores Object Dim oStore 'Store Object Dim bstrPStoreName 'Public Store Name Dim lmask 'Mask. 'Get important session, folder, msg info Set g_oProcInstance = RouteDetails.ProcInstance Set msgTarget = g_oProcInstance.Message idTargetFolder = EventDetails.FolderID idTargetMessage = EventDetails.MessageID Set g_oPIMsg = g_oProcInstance.Message WriteToLog 0, "Subject: " & msgTarget.Subject Set AMSession = EventDetails.Session Set fldrOutbox = AMSession.Outbox Set g_oSession = EventDetails.session Set g_oMsgIn = RouteDetails.Msg WriteToLog 0,g_oMsgIn.Subject Set g_oFolder = RouteDetails.Folder WriteToLog 0,g_oFolder.Name Set g_oAgentAddEntry = g_oSession.currentuser 'Get sender name. If it does not exist (draft msg), 'get originator name. g_bstrMsgSender = g_oMsgIn.sender.Name If Err Then Err.Clear g_bstrMsgSender = g_oMsgIn.Fields.Item(g_PR_CREATOR_NAME) End If WriteToLog 0,g_bstrMsgSender 'Save message Subject for Trace reasons g_bstrInMsgSubject = g_oPIMsg.subject 'Trap any untrapped failure If Err Then WriteToLog 0,"InitializeObjects returned False" InitializeObjects = False Else WriteToLog 0,"InitializeObjects returned True" InitializeObjects = True End If 'Release objects Set oStore = Nothing Set oStores = Nothing End Function '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' Name: ReleaseGlobalObjects ' Area: Utility ' Desc: Release global objects ' Parm: None ' Retn: None '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Private Sub ReleaseGlobalObjects() on error resume next Set g_oMsgIn = Nothing 'Release in reverse order Set g_oFolder = Nothing Set g_oAgentAddEntry = Nothing Set msgTarget = Nothing Set fldrOutbox = Nothing Set g_oPIMsg = Nothing Set Item = Nothing Set g_oSession = Nothing Set AMSession = Nothing Set g_oProcInstance = Nothing End Sub </SCRIPT>

Категории