Beginner:c# windows service using webDav
Hi All,
Please i need help with the code below. Am trying to create a windows service that deletes emails older than 4 months. Please help me check the DeleteEmail method, the WebDav query in the method and also the ReadEmails method.
I have the code below
Code:
using MSXML2;
using System;
using System.IO;
using System.Xml;
using System.Web;
using System.Text;
using System.Data;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Diagnostics;
using System.Configuration;
using Solutions.Components;
using System.ComponentModel;
using System.ServiceProcess;
using System.Collections.Generic;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace MyService
{
partial class MyService : ServiceBase
{
private static string strExchange, strLogServiceName, strUserName, strPassword;
static bool bInProcess;
private static int iInterval;
private static System.Diagnostics.EventLog oEventLog;
private System.Timers.Timer oTimer;
private static string sQuery;
private static string strEmailsXML, strAttachmentsXML;
private static string strConnection;
public MyService()
{
InitializeComponent();
}
#region " SERVICE START AND STOP METHOD "
protected override void OnStart(string[] args)
{
try
{
iInterval = int.Parse(ConfigurationManager.AppSettings["INTERVAL"]);
strExchange = ConfigurationManager.AppSettings["EXCHANGE"];
strLogServiceName = ConfigurationManager.AppSettings["LOGSERVICENAME"];
strUserName = ConfigurationManager.AppSettings["USERNAME"];
strPassword = ConfigurationManager.AppSettings["PASSWORD"];
strConnection = ConfigurationManager.AppSettings["DBConnStr"];
oEventLog = new EventLog("");
oEventLog.Source = strLogServiceName;
oEventLog.MachineName = "."; // USE LOCAL MACHINE EVENT LOG
oTimer = new System.Timers.Timer();
oTimer.Elapsed += new System.Timers.ElapsedEventHandler(PerformFunction);
oTimer.Interval = iInterval;
oTimer.Enabled = true;
bInProcess = false;
oEventLog.WriteEntry("MyService - Service Started");
}
catch (System.Exception oEx)
{
WriteLog("Timer module" + oEx.StackTrace, 1);
}
}
protected override void OnStop()
{
// ADD CODE HERE TO PERFORM ANY TEAR-DOWN NECESSARY TO STOP YOUR SERVICE.
GC.Collect();
GC.WaitForPendingFinalizers();
}
#endregion
// ON FAILURE WRITE THE ERRORS TO EVENT LOG DEPENDING UPON MACHINE NAME SUPPLIED
private static void WriteLog(string strMessage, int iMessageType)
{
try
{
switch (iMessageType)
{
case 1:
oEventLog.WriteEntry("Error!!\n\n" + strMessage, EventLogEntryType.Error);
break;
default:
oEventLog.WriteEntry(strMessage, EventLogEntryType.Information);
break;
}
}
catch
{
}
}
private static void PerformFunction(object Source, System.Timers.ElapsedEventArgs e)
{
string strInboxURL;
if (!bInProcess)
{
bInProcess = true;
try
{
SqlDataAccess oSQLData = new SqlDataAccess();
DataTable oDataTable = oSQLData.GetDataTable("MyTable");
if (oDataTable.Rows.Count == 0)
{
return;
}
else
{
//READ ALL MAILBOXES IN SEQUENCE
foreach (DataRow oRow in oDataTable.Rows)
{
try
{
//GET MAILBOX NAMES FROM THE DATABASE TABLE AND CALL DeleteEmail FUNCTION
strInboxURL = "http://" + strExchange + "/Exchange/" + oRow[1].ToString() + "/Inbox/Processed/";
//CHECK MAILBOX FOR ANY EMAILS AWAITING TO BE PROCESSED
DeleteEmail(oRow[0].ToString(), strInboxURL, oRow[2].ToString(), oRow[3].ToString(), oRow[4].ToString(), oRow[5].ToString(), oRow[6].ToString());
}
catch (System.Exception oEx)
{
WriteLog("\nMyMailboxes Service:PerformFunction()\n" + oEx.Message, 1);
string strParamError = "Type: " + oRow[0].ToString() + "\n" +
"Mailbox: " + oRow[1].ToString() + "\n" +
"Attachment path: " + oRow[2].ToString() + "\n" +
"DXAgencyID: " + oRow[3].ToString() + "\n" +
"File Type: " + oRow[6].ToString();
SendServiceError(oEx, "MyMailboxesV2", "", "PerformFunction()", strParamError);
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
}
catch (Exception oEx)
{
WriteLog("Method Name:PerformFunction()\n" + oEx.Message + "\n" + oEx.Source + "\n" + oEx.StackTrace, 1);
SendServiceError(oEx, "MyMailboxes", "", "PerformFunction()", "");
}
finally
{
bInProcess = false;
}
InsertServiceExecutionTime(); //Log last execution of this service
}
}
private static void DeleteEmail(string strInboxURL)
{
DataTable oDTEmails;
DateTime dtDate = System.DateTime.Now.AddMonths(-4);
try
{
MSXML2.ServerXMLHTTP40 oXmlHttp = new MSXML2.ServerXMLHTTP40();
System.Xml.XmlDataDocument xmlDOMParams = new System.Xml.XmlDataDocument();
oXmlHttp.open("SEARCH", strInboxURL, false, strUserName, strPassword);
sQuery = "<?xml version=\"1.0\"?>" +
"<g:searchrequest xmlns:g=\"DAV:\">" +
"<g:sql>SELECT \"DAV:href\", " +
"\"urn:schemas:httpmail:subject\", " +
"\"urn:schemas:httpmail:from\"" +
"\"urn:schemas:httpmail:date\", " +
"FROM SCOPE('SHALLOW TRAVERSAL OF \"" + strInboxURL + "\"')" +
" WHERE \"DAV:ishidden\"=false AND \"DAV:isfolder\" = false AND " +
"\"urn:schemas:httpmail:datereceived\" <= " + dtDate +
"</g:sql>" +
"</g:searchrequest>";
// SET UP REQUEST HEADERS
oXmlHttp.setRequestHeader("Content-Type", "text/xml");
oXmlHttp.setRequestHeader("Translate", "f");
oXmlHttp.setRequestHeader("Depth", "0");
// SEND THE QUERY
oXmlHttp.send(sQuery.ToString());
strEmailsXML = oXmlHttp.responseText;
}
catch (Exception oEx)
{
WriteLog("Method Name:DeleteEmail()\nProblem accessing mailbox.\n" + oEx.Message + "\n" + oEx.Source + "\n" + oEx.StackTrace, 1);
throw new Exception("Method Name:DeleteEmail()\nProblem accessing mailbox.\n" + oEx.Message);
}
try
{
// READ EMAILS FROM XML RESPONSE
oDTEmails = ReadEmails(strEmailsXML);
// LOOP THROUGH EACH EMAIL AND DELETE
foreach (DataRow oEmailRow in oDTEmails)
{
oEmailRow.Delete();
}
}
catch (Exception oEx)
{
throw new Exception("Method Name:DeleteEmail()\nProblem processing attachments.\n" + oEx.Message);
}
}
private static DataTable ReadEmails(string strXML)
{
DataTable oDTEmails;
DataRow oEmailRow;
oDTEmails = new DataTable();
oDTEmails.Columns.Add(new DataColumn("EmailSubject", typeof(string)));
oDTEmails.Columns.Add(new DataColumn("EmailURL", typeof(string)));
oDTEmails.Columns.Add(new DataColumn("EmailSender", typeof(string)));
// READ THE XML STRING THROUGH STRINGREADER
StringReader stream = new StringReader(strXML);
// CREATE NEW XMLDOCUMENT
XPathDocument doc = new XPathDocument(stream);
// CREATE NAVIGATOR FOR ITERATING INTO NODES
XPathNavigator navigator = doc.CreateNavigator();
// SET UP NAMESPACE MANAGER FOR XPATH
XmlNamespaceManager ns = new XmlNamespaceManager(navigator.NameTable);
ns.AddNamespace("a", "DAV:");
ns.AddNamespace("d", "urn:schemas:httpmail:");
// GET FORECAST WITH XPATH
XPathNodeIterator nodes = navigator.Select("//a:response//a:propstat//a:prop", ns);
try
{
while (nodes.MoveNext())
{
XPathNavigator node = nodes.Current;
if (node.NodeType == XPathNodeType.Element)
{
if (node.HasChildren == true)
{
oEmailRow = oDTEmails.NewRow();
node.MoveToFirstChild();
do
{
switch (node.Name)
{
case "d:subject":
if (node.Value.Length > 1)
{
oEmailRow["EmailSubject"] = node.Value.ToString(); // ADD EMAIL SUBJECT TO DATATABLE
}
break;
case "a:href":
if (node.Value.Length > 1)
{
oEmailRow["EmailURL"] = node.Value.ToString(); // ADD EMAIL URL TO DATATABLE
}
break;
case "d:from":
if (node.Value.Length > 1)
{
oEmailRow["EmailSender"] = node.Value.ToString(); // ADD EMAIL SUBJECT TO DATATABLE
}
break;
}
} while (node.MoveToNext());
oDTEmails.Rows.Add(oEmailRow); // BIND NEW ROW TO DATATABLE
}
}
}
}
catch (Exception oEx)
{
WriteLog("Method Name:ReadEmails()\n" + oEx.Message, 1);
throw new Exception("Method Name:ReadEmails()\n" + oEx.Message);
}
return oDTEmails;
}
public static void SendServiceError(Exception oEx, string strServiceName, string strID,string strMethod,string strParam)
{
string strError = "",
// , strMethod = "Not Supplied", strParam = "Not Supplied",
strAction = "";
string strErrorDescription = "";
try
{
strErrorDescription = oEx.Message;
if (strMethod == "")
{
strMethod = "Not Supplied";
}
if (strParam == "")
{
strParam = "Not Supplied";
}
WriteLog(strLogServiceName + ": Error - " + strErrorDescription, 1);
SqlDataAccess oSqlDataAccess = new SqlDataAccess();
oSqlDataAccess.SetParameter("@ServiceName", strLogServiceName + ": " + strServiceName, SqlDbType.VarChar, 50);
oSqlDataAccess.SetParameter("@ErrorMethod", strMethod, SqlDbType.VarChar, 500);
oSqlDataAccess.SetParameter("@Parameters", strParam, SqlDbType.VarChar, 1000);
oSqlDataAccess.SetParameter("@ErrorDescription", strErrorDescription, SqlDbType.VarChar, 1000);
oSqlDataAccess.SetParameter("@Action", strAction, SqlDbType.VarChar, 500);
oSqlDataAccess.SetParameter("@ID", strID, SqlDbType.VarChar, 15);
oSqlDataAccess.ExecuteNonQuery("IAS..SendServiceErrorEmail");
}
catch (Exception oEx1)
{
WriteLog("Method Name:SendServiceError()\nProblem calling IAS..SendServiceErrorEmail.\n" + oEx1.Message + "\n Error = " + strError, 1);
}
}
private static void InsertServiceExecutionTime()
{
SqlDataAccess oSqlDataAccess = new SqlDataAccess();
oSqlDataAccess.SetParameter("@ServiceName", strLogServiceName, SqlDbType.VarChar, 50);
try
{
oSqlDataAccess.ExecuteNonQuery("Maintenance..InsertServiceExecutionTime");
}
catch (Exception oEx)
{
WriteLog("Method Name:InsertServiceExecutionTime()\n" + oEx.Message, 1);
}
}
}
}
Thanks
Re: Beginner:c# windows service using webDav
Really, the way to figure this problem out is to step through the code in a debugger.
Of course, since the code is inside a Windows Service, it isn't all that easy to debug.
What I do to all my Windows Services is set them up so I can debug them easily.
Namely, I add code that detects whether they are running in a console window or as a service.
If they are running as a console (non-service), I simply call the service Start() method; otherwise,
I call the servicebase Run method.
Here's what you do to use this technique:
1) In the project properties, change the Output Type from "Windows Application" to "Console Application". This allows you to 'print' out any trace statements with Console.WriteLine.
2) Add the following code to the ServiceBase derived class to detect whether running under a console window.
Code:
private const int StdOutputHandle = -11;
/// <summary>
/// Checks if we are running from a console
/// </summary>
///<returns>true if running from the console</returns>
public static bool IsRunningFromConsole()
{
// If the Standard output handle is empty then we are running as a service
return GetStdHandle(StdOutputHandle) != IntPtr.Zero;
}
[DllImport("kernel32.dll", SetLastError = true)]
[SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
private static extern IntPtr GetStdHandle(int nStdHandle);
3) Add a static method to the ServiceBase derived class. This method runs the code in a console window or as a service.
Code:
/// <summary>
/// Call this method to Start the service
/// </summary>
public static void Start(string applicationName)
{
// If not running as a Windows service, manually start the service
if IsRunningFromConsole())
{
try
{
Console.WriteLine( String.Format("Starting the {0}...", applicationName) );
// Start the service in the console
new MyService().OnStart(null);
Console.WriteLine("Service has been started!");
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("Press ENTER to exit.");
Console.ReadLine();
}
else
{
// Run as a Windows Service
Run(new ServiceBase[] { new MyService() });
}
}
4) Change the program main to call the static MyService.Start() method.
Code:
static void Main()
{
// Start the service
MyService.Start( "MyServiceName" );
}
5) Put a break point inside the overloaded Start method and debug away.
Re: Beginner:c# windows service using webDav
You can also refer to this article where I describe how to debug a service while it is running as a service.
http://forums.codeguru.com/showthrea...indows-Service