donderdag 24 maart 2011

Cumulative update package 2 for BizTalk Server 2009

Microsoft has released CU2 for BizTalk Server 2009 and details can be found here:
Cumulative update package 2 for BizTalk Server 2009

BELUX MSDN and TechNet Desktop Gadget

Stay up to date with the latest news from MSDN and TechNet in Belgium and Luxembourg via the new desktop gadget for Windows Vista and Windows 7. It’s free, easy to install and very practical: you won’t miss anything of the latest tech news, blogs, videos and event registrations, as they are all fed right into your desktop!

Downoad: http://gallery.live.com/LiveItemDetail.aspx?li=1f7425ec-9b30-4d71-ac92-242837a10c41
Blog: Install the BELUX MSDN and TechNet Desktop Gadget to stay up to date - Katrien DG's MSDN Blog

woensdag 23 maart 2011

BizTalk monitoring, PART 2: BTS suspended messages

We've written some code to receive an E-mail when a message is suspended in Biztalk. For this code we've created a scheduled task that is triggered when an error is raised by Biztalk.

First of all I'll show how to setup such a triggered event. Just make a new scheduled task in your windows task scheduler. To start the task you add a new trigger, here's a screenshot from how to set up this trigger:


Then click on the 'Edit event filter' button.
Following screenshot shows you how to configure the trigger to the Biztalk 2009 Errors:


Now that the trigger is set, just configure the scheduled task to run the programming code. Just like the BizTalk monitoring tool of my previous post, the configuration is done in an external XML File.

So here is the used code the send us an E-mail with an overview of suspended messages, including the error details and the receiving port. The method will return a boolean to specify if there are no suspended messages.


   1:  public Boolean CheckBTSQueue()
   2:          {
   3:              String tab = "    ";
   4:              //Constant Values
   5:              String ErrorMessage = tab + "<b><i>Suspended message with error at {0}:</i></b><BR>" +
   6:                  tab + tab + "Receive Port: {1}<BR>" +
   7:                  tab + tab + "Error Code: {2}<BR>" + 
   8:                  tab + tab + "Error Description: {3}<BR><BR>";
   9:                  //tab + tab + "Inner Exception: {3}";
  10:              String ErrorSuspendedMsgHeader = "<strong>WARNING: Suspended Message(s) in Biztalk</strong><BR><BR>";
  11:              String MailSubject = "Messages stuck on " + Dns.GetHostName();
  12:   
  13:              StringBuilder suspendedMessages = new StringBuilder();
  14:   
  15:              Boolean allRunning = true;
  16:   
  17:              BizTalkOperations operation = new BizTalkOperations(dBServer, dB);
  18:   
  19:              int count = 10;
  20:              foreach (BizTalkMessage message in operation.GetMessages())
  21:              {
  22:                  if (message.MessageStatus == MessageStatus.Suspended)
  23:                  {
  24:                      suspendedMessages.AppendLine(String.Format(ErrorMessage, message.CreationTime.ToString(),
  25:                          message.Context.Read("PortName", "http://schemas.microsoft.com/BizTalk/2003/messagetracking-properties"), message.ErrorCode, message.ErrorDescription));
  26:                      //message.Context.Read("Name", "NameSpace");
  27:   
  28:                      count--;
  29:   
  30:                      allRunning = false;
  31:                  }
  32:                  if (count <= 0)
  33:                  {
  34:                      count--;
  35:                      break;
  36:                  }
  37:              }
  38:   
  39:              if (!allRunning)
  40:              {
  41:                  if (!String.IsNullOrEmpty(suspendedMessages.ToString()))
  42:                      suspendedMessages.Insert(0, ErrorSuspendedMsgHeader);
  43:   
  44:                  String body = "";
  45:   
  46:                  if (count < 0)
  47:                      body = "Only last 10 messages are given<BR><BR>";
  48:   
  49:                  body += suspendedMessages.ToString();
  50:   
  51:                  Helper.SendMail(body, MailSubject, sendMailAddress, receiveMailAddress, SMTP);
  52:              }
  53:   
  54:              return false;
  55:          }

the method to send an email, the method to read the configuration from XML and the XML itself are the same as in my previous Blog. Here they are again:

the method to send an email is the following:


   1:  public static void SendMail(String body, String subject, String fromAddress, String toAddress, String SMTPAddress)
   2:          {
   3:              MailMessage msg = new MailMessage(fromAddress, toAddress);
   4:              msg.IsBodyHtml = true;
   5:              msg.Body = body;
   6:              //msg.From = new MailAddress(fromAddress);
   7:              msg.Subject = subject;
   8:   
   9:              System.Net.Mail.SmtpClient smtp = new SmtpClient(SMTPAddress);
  10:              smtp.Send(msg);
  11:              //SmtpMail.SmtpServer = SMTPAddress;
  12:              //SmtpMail.Send(msg);
  13:          }

to read the configuration out of the XML file, we've programmed following in the constructor (all is read to private class variables:


   1:  private string dBServer;
   2:          private string dB;
   3:          private string userName;
   4:          private string password;
   5:   
   6:          private List<string> BTSService;
   7:   
   8:          private string sendMailAddress;
   9:          private string receiveMailAddress;
  10:          private string SMTP;
  11:   
  12:          public Monitor()
  13:          {
  14:              XmlDocument config = new XmlDocument();
  15:              config.Load(System.IO.Directory.GetCurrentDirectory() + "/BTSMonitorConfiguration.xml");
  16:   
  17:              try
  18:              {
  19:                  dBServer = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Server").InnerText;
  20:                  dB = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/DB").InnerText;
  21:                  userName = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/UserName") == null ?
  22:                      "" : config.SelectSingleNode("CONFIGURATION/DBSETTINGS/UserName").InnerText;
  23:                  password = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Password") == null ?
  24:                      "" : config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Password").InnerText;
  25:   
  26:                  BTSService = new List<string>();
  27:   
  28:                  foreach(XmlNode service in config.SelectNodes("CONFIGURATION/BTSSETTINGS/BTSSERVICES/BTSServiceName"))
  29:                  {
  30:                      BTSService.Add(service.InnerText);
  31:                  }
  32:   
  33:                  sendMailAddress = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/From").InnerText;
  34:                  receiveMailAddress = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/To").InnerText;
  35:                  SMTP = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/SMTP").InnerText;
  36:              }
  37:              catch (Exception e)
  38:              {
  39:                  StringBuilder error = new StringBuilder();
  40:                  error.AppendLine("not all necessary data to perform the action is provided.");
  41:                  error.AppendLine("Make sure these fields are correctly filled in in the XML File:");
  42:                  error.AppendLine("\tDBServer (server name)");
  43:                  error.AppendLine("\tDB (Database)");
  44:                  error.AppendLine("\tBTSServiceName (BTS Service Name)");
  45:                  error.AppendLine("\tFrom (sending mail address)");
  46:                  error.AppendLine("\tTo (receiveing mail address)");
  47:                  error.AppendLine("\tSMTP (SMTP host address)");
  48:                  throw (new Exception(error.ToString()));
  49:              }
  50:          }


and finally the created XML file:


<?xml version="1.0" encoding="utf-8" ?>
<CONFIGURATION>
  <DBSETTINGS>
    <Server>.</Server>    <!-- Server Name -->
    <DB>BizTalkMgmtDb</DB>    <!-- DataBase Name -->
    <!--<UserName>user</UserName>-->    <!-- optional -->
    <!--<Password>password</Password>-->    <!-- optional -->
  </DBSETTINGS>
  <BTSSETTINGS>
    <BTSSERVICES>
      <BTSServiceName>BizTalk Service BizTalk Group : BizTalkServerApplication</BTSServiceName>      <!-- BTS Service Name -->
      <BTSServiceName>BizTalk Service BizTalk Group : BizTalkServerApplication2</BTSServiceName>
      <!-- BTS Service Name -->
    </BTSSERVICES>
  </BTSSETTINGS>
  <MAILSETTINGS>
    <From>from@company.com</From>
    <To>to@company.com</To>
    <SMTP>smtp.company.com</SMTP>
  </MAILSETTINGS>
</CONFIGURATION>



In this example, only the last 10 suspended messages are mailed to us.

These monitoring mails have proven to be very valuable to us.
Hope you enjoyed my post.

dinsdag 22 maart 2011

Visual Studio 2010 Service Pack 1 Released

Service Pack 1 for Visual studio is now released. Preliminary support is added for HTML5, the IntelliSense also nows all html5 tags.
Other new features in this SP1 for Visual Studio 2010 can be found here

download: Download details: Microsoft Visual Studio 2010 Service Pack 1 (Installer)

maandag 14 maart 2011

BizTalk monitoring, PART 1: BTS services and configurations

For the monitoring of the BizTalk Server we've programmed a simple application that will send an email if a certain port or orchestration will be disabled... or even worse, when a BizTalk Service is stopped.
The configuration for the app is done in an external XML file.

Below is the code that is used to check the BTS status, the method will return a boolean that indicates if all is running or not.


   1:  /// <summary>
   2:          /// Checks the BizTalk Status for BTS Service, Orchestrations, Send Ports, Receive Locations
   3:          /// And send a mail on not running of any instance
   4:          /// </summary>
   5:          /// <returns>True if all is running</returns>
   6:          public Boolean CheckBTSStatus()
   7:          {
   8:              //Constant Values
   9:              String ErrorMessage = "&nbsp;&nbsp;&nbsp;&nbsp;{0} '{1}' is {2}!<BR>";
  10:              String ErrorServicesHeader = "<FONT color=\"#C11B17\"><strong>CRITICAL ISSUE: BTS SERVICE IS STOPPED</strong></FONT><BR><BR>";
  11:              String ErrorReceiveLocationsHeader = "<BR><strong>WARNING: Receive Location issue(s)</strong><BR><BR>";
  12:              String ErrorSendportsHeader = "<BR><strong>WARNING: Send Port issue(s)</strong><BR><BR>";
  13:              String ErrorOrchestrationsHeader = "<BR><strong>WARNING: Orchestration issue(s)</strong><BR><BR>";
  14:              String MailSubject = "URGENT: BizTalk issue(s) on " + Dns.GetHostName();
  15:   
  16:              // separate ERROR StringBuilders
  17:              StringBuilder services = new StringBuilder();
  18:              StringBuilder sendports = new StringBuilder();
  19:              StringBuilder receiveLocations = new StringBuilder();
  20:              StringBuilder orchestrations = new StringBuilder();
  21:              Boolean allRunning = true;
  22:   
  23:              foreach (String service in BTSService)
  24:              {
  25:                  ServiceController sc = new ServiceController(service);
  26:   
  27:                  if (sc.Status != ServiceControllerStatus.Running && sc.Status != ServiceControllerStatus.StartPending)
  28:                  {
  29:                      services.AppendLine(String.Format(ErrorMessage, "Service", service, sc.Status));
  30:                      allRunning = false;
  31:                  }
  32:              }
  33:              
  34:              String connectionString = "Data Source=" + dBServer + ";Initial Catalog=" + dB + ";";
  35:              if (!String.IsNullOrEmpty(userName) && !String.IsNullOrEmpty(password))
  36:                  connectionString += "User Id=" + userName + ";Password=" + password + ";";
  37:              else
  38:                  connectionString += "Integrated Security=SSPI;";
  39:   
  40:              BtsCatalogExplorer catalog = new BtsCatalogExplorer();
  41:              catalog.ConnectionString = connectionString;
  42:   
  43:              foreach (Application app in catalog.Applications)
  44:              {
  45:                  if (app.Status != Status.Started && app.Status != Status.NotApplicable)
  46:                  {
  47:                      foreach (SendPort send in app.SendPorts)
  48:                      {
  49:                          if (send.Status != PortStatus.Started)
  50:                          {
  51:                              sendports.AppendLine(String.Format(ErrorMessage, "Send Port", send.Name, send.Status == PortStatus.Bound ? "Unenlisted" : send.Status.ToString()));
  52:                              allRunning = false;
  53:                          }
  54:                      }
  55:                      foreach (ReceivePort receive in app.ReceivePorts)
  56:                      {
  57:                          foreach (ReceiveLocation location in receive.ReceiveLocations)
  58:                          {
  59:                              if (!location.Enable)
  60:                              {
  61:                                  receiveLocations.AppendLine(String.Format(ErrorMessage, "Receive Location", location.Name, "Disabled"));
  62:                                  allRunning = false;
  63:                              }
  64:                          }
  65:                      }
  66:                      foreach (BtsOrchestration orch in app.Orchestrations)
  67:                      {
  68:                          if (orch.Status != OrchestrationStatus.Started)
  69:                          {
  70:                              orchestrations.AppendLine(String.Format(ErrorMessage, "Orchestration", orch.FullName, orch.Status));
  71:                              allRunning = false;
  72:                          }
  73:                      }
  74:                  }
  75:              }
  76:              
  77:              if(!allRunning)
  78:              {
  79:                  if(!String.IsNullOrEmpty(services.ToString()))
  80:                      services.Insert(0, ErrorServicesHeader);
  81:                  if (!String.IsNullOrEmpty(sendports.ToString()))
  82:                      sendports.Insert(0, ErrorSendportsHeader);
  83:                  if (!String.IsNullOrEmpty(receiveLocations.ToString()))
  84:                      receiveLocations.Insert(0, ErrorReceiveLocationsHeader);
  85:                  if (!String.IsNullOrEmpty(orchestrations.ToString()))
  86:                      orchestrations.Insert(0, ErrorOrchestrationsHeader);
  87:   
  88:                  String body = services.ToString() + receiveLocations.ToString()
  89:                      + sendports.ToString() + orchestrations.ToString();
  90:   
  91:                  Helper.SendMail(body, MailSubject, sendMailAddress, receiveMailAddress, SMTP);
  92:              }
  93:              return allRunning;
  94:          }


the method to send an email is the following:


   1:  public static void SendMail(String body, String subject, String fromAddress, String toAddress, String SMTPAddress)
   2:          {
   3:              MailMessage msg = new MailMessage(fromAddress, toAddress);
   4:              msg.IsBodyHtml = true;
   5:              msg.Body = body;
   6:              //msg.From = new MailAddress(fromAddress);
   7:              msg.Subject = subject;
   8:   
   9:              System.Net.Mail.SmtpClient smtp = new SmtpClient(SMTPAddress);
  10:              smtp.Send(msg);
  11:              //SmtpMail.SmtpServer = SMTPAddress;
  12:              //SmtpMail.Send(msg);
  13:          }


to read the configuration out of the XML file, we've programmed following in the constructor (all is read to private class variables:


   1:  private string dBServer;
   2:          private string dB;
   3:          private string userName;
   4:          private string password;
   5:   
   6:          private List<string> BTSService;
   7:   
   8:          private string sendMailAddress;
   9:          private string receiveMailAddress;
  10:          private string SMTP;
  11:   
  12:          public Monitor()
  13:          {
  14:              XmlDocument config = new XmlDocument();
  15:              config.Load(System.IO.Directory.GetCurrentDirectory() + "/BTSMonitorConfiguration.xml");
  16:   
  17:              try
  18:              {
  19:                  dBServer = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Server").InnerText;
  20:                  dB = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/DB").InnerText;
  21:                  userName = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/UserName") == null ?
  22:                      "" : config.SelectSingleNode("CONFIGURATION/DBSETTINGS/UserName").InnerText;
  23:                  password = config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Password") == null ?
  24:                      "" : config.SelectSingleNode("CONFIGURATION/DBSETTINGS/Password").InnerText;
  25:   
  26:                  BTSService = new List<string>();
  27:   
  28:                  foreach(XmlNode service in config.SelectNodes("CONFIGURATION/BTSSETTINGS/BTSSERVICES/BTSServiceName"))
  29:                  {
  30:                      BTSService.Add(service.InnerText);
  31:                  }
  32:   
  33:                  sendMailAddress = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/From").InnerText;
  34:                  receiveMailAddress = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/To").InnerText;
  35:                  SMTP = config.SelectSingleNode("CONFIGURATION/MAILSETTINGS/SMTP").InnerText;
  36:              }
  37:              catch (Exception e)
  38:              {
  39:                  StringBuilder error = new StringBuilder();
  40:                  error.AppendLine("not all necessary data to perform the action is provided.");
  41:                  error.AppendLine("Make sure these fields are correctly filled in in the XML File:");
  42:                  error.AppendLine("\tDBServer (server name)");
  43:                  error.AppendLine("\tDB (Database)");
  44:                  error.AppendLine("\tBTSServiceName (BTS Service Name)");
  45:                  error.AppendLine("\tFrom (sending mail address)");
  46:                  error.AppendLine("\tTo (receiveing mail address)");
  47:                  error.AppendLine("\tSMTP (SMTP host address)");
  48:                  throw (new Exception(error.ToString()));
  49:              }
  50:          }


and finally the created XML file:


<?xml version="1.0" encoding="utf-8" ?>
<CONFIGURATION>
  <DBSETTINGS>
    <Server>.</Server>    <!-- Server Name -->
    <DB>BizTalkMgmtDb</DB>    <!-- DataBase Name -->
    <!--<UserName>user</UserName>-->    <!-- optional -->
    <!--<Password>password</Password>-->    <!-- optional -->
  </DBSETTINGS>
  <BTSSETTINGS>
    <BTSSERVICES>
      <BTSServiceName>BizTalk Service BizTalk Group : BizTalkServerApplication</BTSServiceName>      <!-- BTS Service Name -->
      <BTSServiceName>BizTalk Service BizTalk Group : BizTalkServerApplication2</BTSServiceName>
      <!-- BTS Service Name -->
    </BTSSERVICES>
  </BTSSETTINGS>
  <MAILSETTINGS>
    <From>from@company.com</From>
    <To>to@company.com</To>
    <SMTP>smtp.company.com</SMTP>
  </MAILSETTINGS>
</CONFIGURATION>


Hope you enjoyed my post.
In my next blog I'll show you how to monitor the BizTalk Queue to receive an email with the error message of all suspended instances.

woensdag 9 maart 2011

woensdag 2 maart 2011

SQL Server training

24 Hours of PASS wants to celebrate women in Technology.

It brings an exceptional lineup of women SQL and BI experts from around the world.
Join for 24 webcasts over two days starting at 12:00 GMT (UTC) on March 15.
Visit www.sqlpass.org/24hours for more info.

this event consists of several live meetings on SQL Server.
Regestration for some (or all) of the meetings can be done here.