I am creating a VSTO Ribbon AddIn for excel, and I am storing some workbook state information in my application that I use to update visual Buttons Enabled. Considering there can be multiple workbooks I am storing this state object in a dictionary in the ThisAddIn class. My problem is that I don't know how to get a unique Hash/Key/Guid for the workbook because all I get is a COM wrapper that continually changes the hash. fair enough, I totally understand that.
One solution I've used for a long time has been to create a guid and store it in the CustomDocumentProperties for the workbook, and to map the state based on that as a key. This at least works, but it fails if I create a copy of the workbook and open that in the same Application instance and have multiple workbooks with the same guid now..
I just had an idea now that I suppose I could refresh this Guid on the Workbook_Open event. But still this seems like a dodgy solution.
The second solution I found here: http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/04efa74d-83bd-434d-ab07-36742fd8410e/
So I used that guys code and created this:
public static class WorkbookExtensions
{
public static IntPtr GetHashery(this msExcel.Workbook workbook)
{
IntPtr punk = IntPtr.Zero;
try
{
punk = Marshal.GetIUnknownForObject(workbook);
return punk;
}
finally
{
//Release to decrease ref count
Marshal.Release(punk);
}
}
}
It works very well for a few minutes, until it starts giving me the infamous error "COM object that has been separated from its underlying RCW cannot be used" when accessing the Application.ActiveWorkbook.
Is this a safe way of referencing the Workbook COM object? What if I had two ribbon applications both using this method to get a single workbooks GUID? What if one of those applications runs the garbage collector on my state object, which calls a finalizer to call Marshal.FinalReleaseComObject(workbook)? Is there any way I can get the Ref Count for a Workbook so that I don't call FinalRelease before other Ribbon Apps have finished with them? What are some best practices for cleaning up Workbook COM objects in VSTO to keep playing fair with these other apps?
Surely I'm not the first person to want to have buttons enabled based on Workbook state, how does everyone else do this? I've looked at a few other articles here on Stack Overflow but none quite help me with the Workbook Guid solution.
I am using the Ribbon Designer, and hooking up to the Workbook Load and Deactivate events.
Thanks in advance, hope ive included all the details.