Keep reference to COM object passed as argument (gets separated from RCW)

Add-in Express™ Support Service
That's what is more important than anything else

Keep reference to COM object passed as argument (gets separated from RCW)
 
gjvdkamp




Posts: 56
Joined: 2018-08-28
I found the sentence that I should release any COM references I create, except the ones passed as arguments.
I'm assuming that ADX will clean up the latter?

My issue is that I have an Excel add-in, where I want to keep a list of extra information about a workbook.

So I have this code:

private void adxExcelAppEvents1_NewWorkbook(object sender, object hostObj){
  ...
  myClass.Workbook = (Excel.Workbook)hostObj;
  MyList.Add(MyClass);
  ... 

}

Where I keep the reference passed through HostObj. However, when later I want to use that Workbook reference on a WorkbookActivate event where I look for the corresponding myClass, I get the 'COM object that has been separated from its underlying RCW cannot be used':


private void adxExcelAppEvents1_WorkbookActivate(object sender, object hostObj)
 ...       {            
  var mc = MyList.FirstOrDefault(x => x.Workbook == (Excel.Workbook)hostObj; // RCW error thrown
...

}


Is this because ADX cleans up the COM reference on Workbook after NewWorkbook ends? (Still learning this).

Should I store a value property like the name to find it back maybe? Is there anything I can use besides Name, as people might rename workbooks and thing could get messed up.
Posted 03 Sep, 2018 07:50:23 Top
gjvdkamp




Posts: 56
Joined: 2018-08-28
And in general, how could I keep the reference to the workbook for a long time, basically until it is closed again?
Would it create problems for ADX if I write
Marshall.AddRef(wb)
to keep the COM object alive?
Posted 03 Sep, 2018 08:11:32 Top
gjvdkamp




Posts: 56
Joined: 2018-08-28
Was able to circumvent the issue by getting a new reference from the ExcelApp, let me know if you have any reservations with this approach.


var wbo = (Excel._Workbook)hostObj;
MyClass.Workbook = ExcelApp.Workbooks[wbo.Name];
Posted 03 Sep, 2018 10:57:58 Top
Andrei Smolin


Add-in Express team


Posts: 18817
Joined: 2006-05-11
Hello,

gjvdkamp writes:
I'm assuming that ADX will clean up the latter?


Exactly. Most often the COM objects passed to your code are released as soon as the event handler completes. Still, there are numerous exceptions to this so I wouldn't advise anyone to rely on this.


gjvdkamp writes:
myClass.Workbook = (Excel.Workbook)hostObj;


Since myClass.Workbook and hostObj point to the same COM object (this is tru in .NET), they will be released as soon as the event handler completes. In Office, it is possible to create a new instance of that COM object. In your case, you do this as follows:

- get string wbkName = (hostObj as Excel.Workbook).Name and store it on the class level;
- let Add-in Express release hostObj
- create a new Workbook object via: ExcelApp.Workbooks[wbkName]; in VB.NET: ExcelApp.Workbooks.Item(wbkName)


Andrei Smolin
Add-in Express Team Leader
Posted 03 Sep, 2018 10:58:18 Top
Andrei Smolin


Add-in Express team


Posts: 18817
Joined: 2006-05-11
gjvdkamp writes:
Was able to circumvent the issue by getting a new reference from the ExcelApp, let me know if you have any reservations with this approach.


It's okay.


Andrei Smolin
Add-in Express Team Leader
Posted 03 Sep, 2018 10:59:32 Top