PowerShell Script To Monitor Biztalk Services Across Multiple Groups
Problem Scenario
One of many duties of a Biztalk Admin is to monitor the status of the Biztalk Services across all the BizTalk Environments. These services are but not limited to :
- Biztalk Host Instances
- Biztalk Rule Engine
- IIS Admin Service
- World Wide Web Publishing Service
- SQL Server Service
- SQL Agent Service
- Integration Services
- RuleUpdate Service
- MSDTC service.
Checking the status of the service on a Single Multi-Server Environment is a manageable task, but what if the number of environments is large, then doing this manually becomes cumbersome and boring and can lead to errors.
Solution
PowerShell is a very powerful tool in the arsenal of an Administrator. Using Power Shell the task becomes automated and can be completed within minutes as compared to an hour or two long task if done manually.
Design
The PowerShell uses a config file which is as shown below.
<Configuration>
<Servers>
<Server>
<Name>LocalHost</Name>
<Type>App</Type>
</Server>
<Server>
<Name>LocalHost</Name>
<Type>App</Type>
</Server>
<Server>
<Name>LocalHost</Name>
<Type>Db</Type>
</Server>
</Servers>
<ServerType>
<Type>App</Type>
<ServiceName>BTS*</ServiceName>
<ServiceName>ENTSSO</ServiceName>
<ServiceName>IISADMIN</ServiceName>
<ServiceName>W3SVC</ServiceName>
<ServiceName>RuleEngineUpdateService</ServiceName>
<ServiceName>MSDTC</ServiceName>
</ServerType>
<ServerType>
<Type>Db</Type>
<ServiceName>MSDTC</ServiceName>
<ServiceName>ClusSvc</ServiceName>
<ServiceName>SQLBrowser</ServiceName>
<ServiceName>MsDtsServer100</ServiceName>
<ServiceName>MsDtsServer120</ServiceName>
<ServiceName>MSSQLServerOLAPService</ServiceName>
<ServiceName>SQLsafe Backup Service</ServiceName>
<ServiceName>MSSQLSERVER</ServiceName>
<ServiceName>SQLSERVERAGENT</ServiceName>
</ServerType>
<ServerType>
<Type>Web</Type>
<ServiceName>MSDTC</ServiceName>
<ServiceName>W3SVC</ServiceName>
</ServerType>
</Configuration>
Here the servers are segregated based on their type whether they are Application Server(BizTalk Application Server), DB(BizTalk Database Server) or a Web Server. The services are segregated according to the server type so that a properly formatted email can be sent. The config file can be used to include different servers and different services
Code
The PowerShell script for getting the service status across the servers is as below.
Function GetServiceStatusesAcrossRemoteServers
{
param
(
#This variable point to the path where the config file is stored.
$strConfigFilePath
)
$PathValidator
$ConnectionValidator
if(test-path $strConfigFilePath)
{
[xml] $Config= Get-Content "$strConfigFilePath\Config.xml"
$Fetchingdata="Hi Team,<b><br/></b><br/>Following is the server wise list of BizTalk Related Services <br/><br/>"
$MailBody= $MailBody+$Fetchingdata
$AppServices= @()
$DbServices=@()
$WebServices=@()
foreach($Configuration in $Config.Configuration)
{
foreach( $ServerType in $Configuration.ServerType)
{
if($ServerType.Type.ToUpper() -eq "APP")
{
#Read the list of the application server related services from the config File
foreach($ServiceName in $ServerType.ServiceName)
{
$AppServices += $ServiceName.ToString()
}
}
if($ServerType.Type.ToUpper() -eq "WEB")
{
#Read the list of the web server related services from the config File
foreach($ServiceName in $ServerType.ServiceName)
{
$WebServices += $ServiceName.ToString()
}
}
if($ServerType.Type.ToUpper() -eq "DB")
{
#Read the list of the Database server related services from the config File
foreach($ServiceName in $ServerType.ServiceName)
{
$DbServices += $ServiceName.ToString()
}
}
}
foreach($Servers in $Configuration.Servers)
{
foreach($Server in $Servers.Server)
{
#Check if The server can be connected to.
if(Test-Connection $Server.Name)
{
$ServerName= $Server.Name
$MailBody= $MailBody+ "Server Name:<b>"+ $ServerName +"</b>:"+$Server.Type.ToUpper()+" Server <br/><br/>"
$style="<style>BODY{background-color:white;}TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse; }TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:#4d79ff }TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:white}</style>"
$head= "<head>$style</head>"
$tableBOdy= "<body><p style='font-size:25px;family:calibri;color:#ff9100'>$style<table><colgroup><col/><col/><col/><col/></colgroup><tr><th>ServiceName</th><th>DisplayName</th><th>ServiceStartType</th><th>ServiceStatus</th></tr>"
# Check the server type
#If the Service is not found on the server, the powershell script will continue silently
#Ignoring the service.
if($Server.Type.ToUpper() -eq "APP")
{
foreach($AppService in $AppServices)
{
$Services= Get-WmiObject -Class Win32_Service -filter "Name like '%$AppService%'" -ComputerName $ServerName
if($Services.Count -gt 1)
{
foreach($Service in $Services)
{
$ServiceName=$Service.Name
$DisplayName=$Service.DisplayName
$ServiceStatus= $Service.State
$ServiceStartType=$Service.StartMode
if($ServiceStatus -eq "Stopped")
{
$ServiceStatus="<font color='Red'>Stopped</font>"
}
if($Service -ne $null)
{
$tableBOdy= $tableBOdy + "<tr><td>$ServiceName</td><td>$DisplayName</td><td>$ServiceStartType</td><td>$ServiceStatus</td></tr>"
}
}
}
else
{
$ServiceName=$Services.Name
$DisplayName=$Services.DisplayName
$ServiceStatus= $Services.State
$ServiceStartType=$Services.StartMode
if($ServiceStatus -eq "Stopped")
{
$ServiceStatus="<font color='Red'>Stopped</font>"
}
if($Services -ne $null)
{
$tableBOdy= $tableBOdy + "<tr><td>$ServiceName</td><td>$DisplayName</td><td>$ServiceStartType</td><td>$ServiceStatus</td></tr>"
}
}
}
$tableBOdy= $tableBOdy+ "</table></body>"
$html="<html>$head$tableBOdy</html>"
$MailBody=$MailBody+ $html+"<br/><br/>"
}
if($Server.Type.ToUpper() -eq "DB")
{
foreach($DbService in $DbServices)
{
$DataServices= Get-WmiObject -Class Win32_Service -filter "Name like '%$DbService%'" -ComputerName $ServerName
if($DataServices.Count -gt 1)
{
foreach($DataService in $DataServices)
{
$ServiceName=$DataService.Name
$DisplayName=$DataService.DisplayName
$ServiceStatus= $DataService.State
$ServiceStartType=$DataService.StartMode
if($ServiceStatus -eq "Stopped")
{
$ServiceStatus="<font color='Red'>Stopped</font>"
}
if($DataService -ne $null)
{
$tableBOdy= $tableBOdy + "<tr><td>$ServiceName</td><td>$DisplayName</td><td>$ServiceStartType</td><td>$ServiceStatus</td></tr>"
}
}
}
else
{
$ServiceName=$DataServices.Name
$DisplayName=$DataServices.DisplayName
$ServiceStatus= $DataServices.State
$ServiceStartType=$DataServices.StartMode
if($ServiceStatus -eq "Stopped")
{
$ServiceStatus="<font color='Red'>Stopped</font>"
}
if($DataServices -ne $null)
{
$tableBOdy= $tableBOdy + "<tr><td>$ServiceName</td><td>$DisplayName</td><td>$ServiceStartType</td><td>$ServiceStatus</td></tr>"
}
}
}
$tableBOdy= $tableBOdy+ "</table></body>"
$html="<html>$head$tableBOdy</html>"
$MailBody=$MailBody+ $html+"<br/><br/>"
}
if($Server.Type.ToUpper() -eq "WEB")
{
foreach($WebService in $WebServices)
{
$WbServices= Get-WmiObject -Class Win32_Service -filter "Name like '%$WebService%'" -ComputerName $ServerName
if($WbServices.Count -gt 1)
{
foreach($WbService in $WbServices)
{
$ServiceName=$WbService.Name
$DisplayName=$WbService.DisplayName
$ServiceStatus= $WbService.State
$ServiceStartType=$WbService.StartMode
if($ServiceStatus -eq "Stopped")
{
$ServiceStatus="<font color='Red'>Stopped</font>"
}
if($WbService -ne $null)
{
$tableBOdy= $tableBOdy + "<tr><td>$ServiceName</td><td>$DisplayName</td><td>$ServiceStartType</td><td>$ServiceStatus</td></tr>"
}
}
}
else
{
$ServiceName=$WbServices.Name
$DisplayName=$WbServices.DisplayName
$ServiceStatus= $WbServices.State
$ServiceStartType=$WbServices.StartMode
if($ServiceStatus -eq "Stopped")
{
$ServiceStatus="<font color='Red'>Stopped</font>"
}
if($WbServices -ne $null)
{
$tableBOdy= $tableBOdy + "<tr><td>$ServiceName</td><td>$DisplayName</td><td>$ServiceStartType</td><td>$ServiceStatus</td></tr>"
}
}
}
$tableBOdy= $tableBOdy+ "</table></body>"
$html="<html>$head$tableBOdy</html>"
$MailBody=$MailBody+ $html+"<br/><br/>"
}
}
else
{
write-Host "Connection to the server"+ $ServerName.Name + "failed"
$ConnectionValidator="Connection to the server:<b>"+$Server.Name+"</b>failed."
}
}
}
}
}
else
{
$PathValidator="Provided Path is invalid."
}
[string]$MailBodyMsg=$PathValidator+$ConnectionValidator+$MailBody+"<br/><br/>Regards,<br/>BizAdmin Team <br/><br/>----------------------------------------------------------------------<br/>This is an autogenerated mail. Please do not reply to it.<br/>"
$Subject= "Service Status Notification on"+(get-date)
[string[]]$users = "xyz@pqr.com"
[string]$fromemail = "xyz@pqr.com"
[string]$server = "SMTP Server Ip or name"
send-mailmessage -from $fromemail -to $users -subject $Subject -BodyAsHTML $MailBodyMsg -priority High -smtpServer $server
Write-Host "Mail Sent successfully...!!!"
}
The only thing that needs to be taken care of is that the user with which the PowerShell script is being executed has right to execute the script on the remote system.
Sample
A sample report for the test is shown below.
Conclusion
PowerShell can be used to automate the task of checking the status of the service instances across multiple BizTalk Environment and the report can be sent via mail to multiple parties of Interest.
Download
The PowerShell Script can be downloaded from the Technet Gallery at below link.
See Also
Another important place to find a huge amount of BizTalk related articles is the TechNet Wiki itself. The best entry point is BizTalk Server Resources on the TechNet Wiki