Basically I modified the workbook slightly to log to a text file. The text file was then monitored by my process using a FileSystemWatcher.
The workbook creates the log file locally on the server. I've had issues in the past with FileSystemWatcher where it monitors a unc path and the network appears to go down causing it to stop working so I was confident that this would be ok.
I think FileSystemWatcher raises the Changed event on a separate thread (not verified) as my service runs the Export() function on a timer thread which would be blocked until the excel macro has finished executing.
As it turns out, the service is happily running and monitoring the file.
internal class myWorkbook : IDisposable
{
private Microsoft.Office.Interop.Excel.Application app = null;
private Microsoft.Office.Interop.Excel.Workbook myWorkbook = null;
private string _myWorkbookUri;
private FileSystemWatcher watcher;
private bool _visible;
private string _logFile;
public myWorkbook(string myWorkbookUri, string)
{
_myWorkbookUri = myWorkbookUri;
}
public string Export(DateTime date)
{
app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = false;
app.DisplayAlerts = false;
app.Interactive = false;
app.AskToUpdateLinks = false;
myWorkbook = app.Workbooks.Open(_myWorkbookUri, 0, true, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "", true, false, 0, true, true, false);
CreateWatcher();
return (string)app.Run("GenerateTextFile", date);
}
private void CreateWatcher()
{
watcher = new FileSystemWatcher();
watcher.Path = Path.GetDirectoryName(_logFile);
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "*.txt"; // could use _logFile;
watcher.Changed += watcher_Changed;
watcher.EnableRaisingEvents = true;
}
void watcher_Changed(object sender, FileSystemEventArgs e)
{
if (e.FullPath == _logFile)
{
using (FileStream fs = new FileStream(_logFile,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (sr.Peek() >= 0)
{
var line = sr.ReadLine();
var tabs = line.Split(new char[] { '\t' });
DateTime eventTime = DateTime.Parse(tabs[0]);
if (DateTime.Compare(eventTime, lastEventTime) > 0)
{
string eventMessage = tabs[1];
OnProgressChanged(new ProgressChangedEventArgs(eventTime, eventMessage));
lastEventTime = eventTime;
}
}
}
}
}
}
}