In this
multipart serie of blogposts, I will try to give some examples to keep an eye
on the monitoring of BizTalk, without having the need to log on to the
environment. Emails will be sent to specific users about certain information.
The second part
of this serie will be tackling dehydrated messages. With some simple scripting,
specific user can be notified when a service instance is in a dehydrated state
for too long. Dehydrated instances can occur when a long running process for
example has been developed, but every instance has a certain “maximum runtime”.
When that runtime is surpassed, we want to have a notification about it that
something might be wrong with the process. What also will be done in this
script is, next to sending just an email, is also including an attachment
containing the message which was processed last by the service instance.
Next to
notifying a user, there is also the option to terminate dehydrated instances
after a certain amount of time to clean out the BizTalk environment. This way,
having instances dehydrated for months can be avoided. The messages are also
stored and the location of this storage is communicated together with the email
notification of a terminate.
First, some
variables are defined and initialized. An argument is needed in this script,
being ‘daily’ or ‘minutely’. This indicates which part of the script needs to
be executed:
- Daily: Check for dehydrated instances (eg. Older than 2 days) and
terminate them
- Minutely: Check for dehydrated instances (eg. Older than 10
minutes)
A temporary file
location is used to temporarily store saved messages. The strEmailAdressesCC
indicates an email address which needs to be in CC of ALL the mails that are
being sent. The terminate instances option indicates whether instances need to
be terminated or not.
Option Explicit
Dim
strBaseTempFilesDir,strEmailAdressesCC,bTerminateInstancesAndDeleteDir,strSchedule,strTimeInterval,strSubject,strBody
If Wscript.Arguments.Count
<> 1 Then
Wscript.Echo "Need
1 argument: 'Daily' or 'Minutely'"
Wscript.Quit(1)
End If
strBaseTempFilesDir =
CreateObject("Wscript.Shell").CurrentDirectory
strEmailAdressesCC = "BizTalkAdministratorGroup@yourcompany.com"
bTerminateInstancesAndDeleteDir
= False
strTimeInterval = "d"
The first of two
large parts in the script will be handling all the ‘minutely’ processing. This
involves checking if there are any instances dehydrated for a certain time, and
informing certain users about this issue. Also the messages will be saved and
sent. The saving and emailing is handled later.
Multiple
instance types can be used within one call to ‘ProcessDehydratedMessages’. In
this case, two calls are being done to this function, with both a different
timestamp. The first call will only be checking the provided instance types
after 10 minutes of dehydration, the second call will be notifying users after
20 minutes of dehydration.
'=======================================================================================================
' Alert
dehydrated instances of Orchestration type(s) older than X minutes and evt.
send email
'=======================================================================================================
If
UCase(Wscript.Arguments(0)) = "MINUTELY"
Then
bTerminateInstancesAndDeleteDir = False
strTimeInterval = "n"
' n for minutes
strSubject = "Dehydrated
instance of: "
strBody = "
is in a dehydrated state." & vbCrLf & "Please find the message in attachment."
& vbCrLf & vbCrLf & "BizTalk is
waiting for a response message:" & vbCrLf
ProcessDehydratedInstances Array("orcOrderManagementFlowXType","orcCustomerRelationsFlowXType"),10,"peter.brown@yourcompany.com;ben.dawson@yourcompany.com"
ProcessDehydratedInstances Array("orcPeopleManagementFlowZType","orcInvoicingReceivalType"),20,"anna.vangel@yourcompany.com;dean.burton@Dexia.com"
Wscript.Quit
The second part
is doing initially the same thing as the part above, but is used to indicate which
instances are dehydrated for too long and will be terminated. At the end of
this part, the script will also delete all currently existing folders which
contain no data.
'=======================================================================================================
' Terminate
dehydrated instances of Orchestration type(s) older than X days and evt. send
email
'=======================================================================================================
If
UCase(Wscript.Arguments(0)) = "DAILY"
Then
bTerminateInstancesAndDeleteDir = True
strTimeInterval = "d"
strSubject = "Terminated
instance of: "
strBody = "
has been in a dehydrated state for too long and is now terminated."
& vbCrLf & "Please find the message in
attachment." & vbCrLf & vbCrLf & "BizTalk is no longer waiting for a response:"
& vbCrLf
ProcessDehydratedInstances Array("orcOrderManagementFlowXType","orcCustomerRelationsFlowXType"),30,"peter.brown@yourcompany.com;ben.dawson@yourcompany.com"
ProcessDehydratedInstances Array("orcPeopleManagementFlowZType","orcInvoicingReceivalType"),2,"anna.vangel@yourcompany.com;dean.burton@Dexia.com"
ProcessDirectoriesForNonexistentServiceInstances
Wscript.Quit
End If
Wscript.Quit
Now, we’re going
to dive deeper into the function ‘ProcessDehydratedInstances’. The function
starts again with defining the WMI elements to connect with the BizTalk server
and to create a current datetime object. The provided date value is deducted
from the current date/time.
Function
ProcessDehydratedInstances (strOrchnames,Interval,strEmailAdresses)
Dim
objWMI,objDatetime,strOrcName,svcInsts,svcInst
Set objWMI = GetObject("winmgmts:\root\MicrosoftBizTalkServer")
Set objDatetime =
CreateObject("WbemScripting.SWbemDateTime")
objDatetime.SetVarDate
DateAdd(strTimeInterval, -Interval, Now)
All the provided instance type names,
stored in the string array ‘strOrchnames’ are being looped and searched for
dehydrated instances on the BizTalk environment. If an email address (or
multiple) is provided, the function SaveAndEmailFiles is called. Read on to see
the details of this function. Also the Boolean bTerminateInstancesAndDeleteDir
is checked. If true, then the instance will be terminated.
For Each strOrcName In
strOrchnames
Set svcInsts
= objWMI.ExecQuery("SELECT * FROM
MSBTS_ServiceInstance WHERE ServiceStatus = 8 AND ServiceName = '"
& strOrcName & "' AND ActivationTime < '" &
objDatetime.Value & "'")
For Each svcInst In
svcInsts
If
strEmailAdresses <> "" Then
SaveAndEmailFiles strOrcName,svcInst.InstanceID,strEmailAdresses,svcInst.ActivationTime
End If
If
bTerminateInstancesAndDeleteDir = True Then
svcInst.Terminate
'Wscript.echo
"Terminated: " & strOrcName & " " &
svcInst.InstanceID
End If
Next
Set svcInsts
= Nothing
Next
Set objDatetime = Nothing
Set objWMI = Nothing
End Function
The
SaveAndEmailFiles function will take care of saving all messages and sending
emails. It starts typically with defining the base for doing WMI calls.
Function SaveAndEmailFiles
(strOrcName,ServiceInstanceID,strEmailAdresses,ActivationTime)
Dim
objWMI,objFSO,objFolder,strInstanceFiles,msgInsts,msgInst, objShell,
strDescription, strCommand
Set objWMI = GetObject("winmgmts:\root\MicrosoftBizTalkServer")
Set objFSO = CreateObject("Scripting.FileSystemObject")
A string is being constructed to save the
messages to. This consists of the instance type name.
strInstanceFiles =
strBaseTempFilesDir & "\" &
strOrcName & "\" &
ServiceInstanceID
Set objShell =
CreateObject("WScript.Shell")
strDescription =
strInstanceFiles
The query is being executed and the
messages are being saved by calling the ‘SaveToFile’ function. Read on to see
the details of this function as well. The ‘SendMail’ function is also called,
as well at a save of messages as a terminate.
If Not objFSO.FolderExists(strInstanceFiles) Then
objFSO.CreateFolder(strInstanceFiles)
Set msgInsts
= objWMI.ExecQuery("SELECT * FROM
MSBTS_MessageInstance WHERE ServiceInstanceID = '" &
ServiceInstanceID & "'")
For Each msgInst In msgInsts
msgInst.SaveToFile strInstanceFiles
Next
SendEmail strInstanceFiles, strOrcName,
ServiceInstanceID, strEmailAdresses,ActivationTime
End If
If
bTerminateInstancesAndDeleteDir = True Then
SendEmail strInstanceFiles, strOrcName,
ServiceInstanceID, strEmailAdresses,ActivationTime
objFSO.DeleteFolder(strInstanceFiles)
End If
End Function
This 'SendEmail' function will construct an email message based on all previously queried values. It takes the name of the orchestration, the files itself, the serviceinstanceID, the activationtime and the email adressees into account. I'll just let the code speak for itself here:
Function SendEmail
(strInstanceFiles, strOrcName, ServiceInstanceID,
strEmailAdresses,ActivationTime)
Dim
objShell,objEnv,objMessage,objFSO,objFiles,objFile,objDatetime
Set objShell =
CreateObject("WScript.Shell")
Set objEnv =
objShell.Environment("Process")
Set objMessage =
CreateObject("CDO.Message")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objDatetime =
CreateObject("WbemScripting.SWbemDateTime")
objDatetime.Value =
ActivationTime
objMessage.From = "BizTalk." & objEnv("BTS_ENVIRONMENT") & "@YourCompany.com"
objMessage.To =
strEmailAdresses
objMessage.Cc =
strEmailAdressesCC
objMessage.Subject =
strSubject & strOrcName
objMessage.Textbody =
vbCrLf & "An instance of "
& strOrcName & strBody _
& "- Orchestration Name: " & strOrcName & vbCrLf
_
& "- Service Instance ID: " & ServiceInstanceID &
vbCrLf _
& "- Activation Time: " &
objDatetime.GetVarDate & vbCrLf
objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing")
= 2
objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate")
= 2
objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver")
= objEnv("BTS_SMTP_HOST")
objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport")
= 25
objMessage.Configuration.Fields.Update
Set objFiles =
objFSO.GetFolder(strInstanceFiles).Files
For Each objFile in
objFiles
objMessage.AddAttachment objFile.Path
Next
objMessage.Send
Set objShell = Nothing
Set objEnv = Nothing
Set objMessage = Nothing
Set objFSO = Nothing
Set objFiles = Nothing
Set objDatetime = Nothing
End Function
The script ends with a little cleanup function. This will remove all the 'empty' generated folders on disk, so that no overhead of folders is created on the server running the script. If no instances for the servicename can be found, it will remove the folder which exists for this specific servicename.
'=======================================================================================================
' Function
ProcessDirectoriesForNonexistentServiceInstances
'=======================================================================================================
Function
ProcessDirectoriesForNonexistentServiceInstances ()
Dim
objFSO,objDirs,objDir,objInstID,objWMI,svcInsts
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objWMI = GetObject("winmgmts:\root\MicrosoftBizTalkServer")
Set objDirs =
objFSO.GetFolder(strBaseTempFilesDir).subFolders
For Each objDir in
objDirs
For Each objInstID in
objDir.subFolders
Set
svcInsts = objWMI.ExecQuery("SELECT * FROM
MSBTS_ServiceInstance WHERE ServiceName = '" & objDir.Name
& "' AND InstanceID = '" &
objInstID.Name & "'")
If
svcInsts.Count = 0 Then
objInstID.Delete
End If
Set
svcInsts = Nothing
Next
Next
Set objWMI = Nothing
Set objFSO = Nothing
End Function
'=======================================================================================================
Wscript.Quit
There, we're through. There is one last post following, handling suspended instances. This last one will maybe be most of use, since it will alert users when an instance is suspended in the BizTalk environment.
Thanks for reading, if you have any remarks
or questions, please leave them in the comments section!
Andrew De Bruyne