My client has an automated instance of MS Word running as a service. The client does not have the source code and has requested I write a utility to monitor this running instance of Word to make sure it is functioning properly. I can monitor Word when a document is loaded and send out a NetSend message to several workstations if the document is sitting in Word in an active state for an extended period of time such as more than 5 minutes. But the problem is when the automated instance goes to "Save as" and gets stuck at that point. So, my question is, how would I determine that the running instance of Word is stuck at the "Save as" stage?
Complete source code of what I have follows:
Code:
#pragma warning disable 0168
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using Office = Microsoft.Office.Core;
using System.Runtime.InteropServices;
using System.Data.OleDb;
using System.Collections;
namespace WordMonitorApplication
{
class ThreadData
{
public int iSeconds = 60;
public int iTotalMinutes = 5;
}
class WordMonitor
{
static void Main(string[] args)
{
ThreadData threaddata = new ThreadData();
if (args.Length > 1)
threaddata.iSeconds = int.Parse(args[1]);
if(args.Length > 2)
threaddata.iTotalMinutes = int.Parse(args[2]);
Console.WriteLine("Parameters: ISeconds = {0} iTotalMinutes = {1}", threaddata.iSeconds, threaddata.iTotalMinutes);
ArrayList myList = new ArrayList();
ReadAccessMDB.ReadMDB(myList);
ThreadContainer objContainer = new ThreadContainer(myList);
Thread objThread = new Thread(new ParameterizedThreadStart(objContainer.RunWordMonitor));
objThread.Start(threaddata);
}
class ThreadContainer
{
ArrayList MyNetNameList;
public ThreadContainer(ArrayList inputList)
{
MyNetNameList = inputList;
}
public void RunWordMonitor(object obj)
{
Word.Application wdapp;
DateTime startTime = DateTime.Now;
bool bMessageSent = false;
string DocName = null;
string TempString = null;
string ErrorMsg;
ThreadData threaddata = (ThreadData)obj;
// CreateLogFiles Err = new CreateLogFiles();
// Err.ErrorLog("error.log","App Started");
while (true)
{
try
{
//Get the reference to Word.Application from the ROT.
wdapp = (Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
wdapp.Activate();
if (String.Compare(DocName, wdapp.ActiveDocument.Name) == 0)
{
DateTime stopTime = DateTime.Now;
TimeSpan duration = stopTime - startTime;
TempString = String.Format("Open File: {0} Duration: {1:0.00}", wdapp.ActiveDocument.Name, duration.TotalMinutes);
// TempString = "Open File: " + wdapp.ActiveDocument.Name + " Duration: " + duration.TotalMinutes + " Minutes";
Console.WriteLine(TempString);
if (duration.TotalMinutes > threaddata.iTotalMinutes)
{
if (bMessageSent == false)
{
bMessageSent = true;
string srcComputer;
//Retrieve the NetBIOS name.
srcComputer = System.Environment.MachineName;
ErrorMsg = "Grid Processor cannot process " + wdapp.ActiveDocument.Name;
foreach (string desComputer in MyNetNameList)
{
// Send the message to all the workstations
SendNetMsg.SendMessage(srcComputer, desComputer, ErrorMsg);
TempString = "Message sent to: " + desComputer;
Console.WriteLine(TempString);
}
}
}
}
else
{
startTime = DateTime.Now;
bMessageSent = false;
DocName = wdapp.ActiveDocument.Name;
// TempString = "In else docName = " + DocName;
// Err.ErrorLog("error.log", TempString);
}
}
catch (Exception ex)
{
// Console.WriteLine(ex.Message);
}
finally
{
//Release the reference.
wdapp = null;
}
Thread.Sleep(1000 * threaddata.iSeconds);
}
}
}
}
public class SendNetMsg
{
const int NERR_Success = 0;
const int NERR_BASE = 2100;
const int NERR_NameNotFound = (NERR_BASE + 173); // The message alias could not be found on the network.
const int NERR_NetworkError = (NERR_BASE + 36); // A general network error occurred.
const int ERROR_ACCESS_DENIED = 5;
const int ERROR_INVALID_PARAMETER = 87;
const int ERROR_NOT_SUPPORTED = 50;
[DllImport("netapi32.dll")]
public static extern int NetMessageBufferSend(
[MarshalAs(UnmanagedType.LPWStr)] string servername,
[MarshalAs(UnmanagedType.LPWStr)] string msgname,
[MarshalAs(UnmanagedType.LPWStr)] string fromname,
[MarshalAs(UnmanagedType.LPWStr)] string buf,
int buflen);
public static void SendMessage(string srcName, string dstName, string Msg)
{
int retVal = NetMessageBufferSend(null, dstName, srcName, Msg, Msg.Length * 2);
if (retVal == NERR_NameNotFound)
Console.WriteLine("Error: NERR_NameNotFound");
else if (retVal == NERR_NetworkError)
Console.WriteLine("Error: NERR_NetworkError");
else if (retVal == ERROR_ACCESS_DENIED)
Console.WriteLine("Error: ERROR_ACCESS_DENIED");
else if (retVal == ERROR_INVALID_PARAMETER)
Console.WriteLine("Error: ERROR_INVALID_PARAMETER");
else if (retVal == ERROR_NOT_SUPPORTED)
Console.WriteLine("Error: ERROR_NOT_SUPPORTED");
else if (retVal != 0)
Console.WriteLine("Unknown error returned.\nError code {0}", retVal);
}
}
public class ReadAccessMDB
{
public static void ReadMDB(ArrayList theArrayList)
{
string connectionString = GetConnectionString();
string queryString =
"SELECT NetName FROM NetNames;";
using (OleDbConnection connection =
new OleDbConnection(connectionString))
{
OleDbCommand command = connection.CreateCommand();
command.CommandText = queryString;
try
{
connection.Open();
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// Console.WriteLine("{0}", reader[0]);
theArrayList.Add(reader[0]);
}
reader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
static private string GetConnectionString()
{
return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
+ "WordMon.mdb;";
}
}
public class CreateLogFiles
{
private string sLogFormat;
private string sErrorTime;
public CreateLogFiles()
{
//sLogFormat used to create log files format :
// dd/mm/yyyy hh:mm:ss AM/PM ==> Log Message
sLogFormat = DateTime.Now.ToShortDateString().ToString() + " " + DateTime.Now.ToLongTimeString().ToString() + " ==> ";
//this variable used to create log filename format "
//for example filename : ErrorLogYYYYMMDD
string sYear = DateTime.Now.Year.ToString();
string sMonth = DateTime.Now.Month.ToString();
string sDay = DateTime.Now.Day.ToString();
sErrorTime = sYear + sMonth + sDay;
}
public void ErrorLog(string sPathName, string sErrMsg)
{
StreamWriter sw = new StreamWriter(sPathName + sErrorTime, true);
sw.WriteLine(sLogFormat + sErrMsg);
sw.Flush();
sw.Close();
}
}
}