F# doesn't support Edit and Continue, so my approach is to create a separate add-in which uses a FileSystemWatcher to watch for changes and reload the main add-in whenever necessary.
The problem I'm having is that the call to XlCall.Excel(XlCall.xlfUnregister...) is failing with an exception. Even though the re-register seems to succeed, the UDFs haven't updated, so I'm guessing the failed Unregister prevented Excel from seeing the new code. It works fine if I do it by hand with File->Open->/path/to/xll
I'm probably doing something stupid. Here's the add-in code for the autoloader... any ideas appreciated...
Also, I'm slightly dubious of the threadsafety of doing this inside a FileSystemWatcher event. Are there any problems you can foresee with this?
<DnaLibrary Name="AutoLoader" Language="C#" RuntimeVersion="v4.0">
<Reference Name="System.Windows.Forms" />
<![CDATA[
using System;
using System.IO;
using System.Windows.Forms;
using ExcelDna.Integration;
// This class implements the ExcelDna.Integration.IExcelAddIn interface.
// This allows the add-in to run code at start-up and shutdown.
public class AutoLoaderAddIn : IExcelAddIn
{
private static object _registerId;
private static FileSystemWatcher _watcher;
private static string _xllDir = @"/path/to/bin";
private static string _xllFile = @"NameOfAddinWithoutExtension";
public void AutoOpen()
{
Register();
// Create a new FileSystemWatcher and set its properties.
_watcher = new FileSystemWatcher();
_watcher.Path = _xllDir;
_watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes
| NotifyFilters.Size;
_watcher.Filter = _xllFile + "-packed.xll";
// Add event handlers.
_watcher.Changed += new FileSystemEventHandler(OnChanged);
_watcher.Created += new FileSystemEventHandler(OnChanged);
_watcher.Deleted += new FileSystemEventHandler(OnChanged);
_watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Begin watching.
_watcher.EnableRaisingEvents = true;
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
Unregister();
Register();
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
Unregister();
Register();
}
private static void Register()
{
//MessageBox.Show("About to register.");
if(_registerId == null)
{
try
{
_registerId = XlCall.Excel(XlCall.xlfRegister, _xllDir + @"\" + _xllFile + ".xll");
}
catch(Exception e)
{
//MessageBox.Show("Register exception " + e.Message);
}
}
}
private static void Unregister()
{
//MessageBox.Show("About to unregister.");
if(_registerId != null)
{
try
{
object success = XlCall.Excel(XlCall.xlfUnregister, _registerId);
_registerId = null;
}
catch(Exception e)
{
//MessageBox.Show("Unregister exception " + e.Message);
}
}
}
public void AutoClose()
{
Unregister();
}
}
]]>
</DnaLibrary>