Get Hashcode for Excel Workbook in VSTO to enable buttons based on state
I ended up solving this by simply casting the IntPtr to an long, and then the disposal of the IntPtr doesn't affect me. I don't need to preserve the IntPtr because all I really need is something unique about the workbook.
The following code allows me to store Workbook-specific state information, so I can update the visual state of the buttons in my ribbon based on a custom object workbook state. You can store any information you'd like in your custom WorkbookState class, but typically it would be session-specific information you don't want to persist in the spreadsheet itself.
Separate Workbook extensions:
public static class WorkbookExtensions
{
public static long GetHashery(this msExcel.Workbook workbook)
{
if (workbook == null)
{
throw new ArgumentNullException("workbook");
}
IntPtr pUnknown = IntPtr.Zero;
try
{
pUnknown = Marshal.GetIUnknownForObject(workbook);
return pUnknown.ToInt64();
}
finally
{
// GetIUnknownForObject causes AddRef.
if (pUnknown != IntPtr.Zero)
{
Marshal.Release(pUnknown);
}
}
}
}
Then in my VSTO/ExcelDna ThisAddIn class I store a map of all workbook states with the above method to find a unique workbook hash key:
private Dictionary<long, WorkbookState> _workbookStates = new Dictionary<long, WorkbookState>();
public WorkbookState WorkbookState
{
get
{
long hash = Application.ActiveWorkbook.GetHashery();
WorkbookState state;
if (!_workbookStates.TryGetValue(hash, out state))
{
state = _workbookStates[hash] = new WorkbookState();
}
return state;
}
}
And of course now I can access my WorkbookState from anywhere in my ribbon application by simply calling ThisAddIn.WorkbookState