This project has moved and is read-only. For the latest updates, please go here.

"Please call NetOffice.Factory.Initialize" error when I try to use dlls compiled from source 1.5.1.2

Feb 8, 2013 at 1:57 PM
Hello!

I am trying to compile NetOffice dlls from sources included in 1.5.1.2, which I downloaded here.
http://netoffice.codeplex.com/releases/view/70943
It gives me
Please call NetOffice.Factory.Initialize error:
NetOffice.NetOfficeException: Please call NetOffice.Factory.Initialize()
at NetOffice.Factory.CreateObjectFromComProxy(COMObject caller, Object comProxy)
at NetOffice.OfficeApi.ICTPFactory.CreateCTP(String cTPAxID, String cTPTitle, Object cTPParentWindow)
But NET 4.0 dlls included in package are working fine.
Does something missing in sources?
Feb 8, 2013 at 9:43 PM
Edited Feb 9, 2013 at 10:10 AM
its possible to post your Addin.cs(or whatever) content for further research?
did you use a self-compiled version from NetOffice?

UPDATE: you have to sign the NetOffice assemblies with .the snk files. please checkout the latest source and the KeyFiles Directory.

why you need own NetOffice assemblies?

if you want sign your assemblies with an own key then you need to modify the KeyFiles.txt in NetOffice.csproj.

Sebastian
Feb 10, 2013 at 8:57 AM
I can create sample add-in, but I think this is not necessary.
It seems that source files, included in an archive from downloads page are not full or not actual. They don't contain KeyFiles folder, so I had to create snk files myself.
I'll check sources from sources page.
Here is the full story.
We are developing an add-in that actively interacts with Word and Outlook, using shared-addin and COM-shim.
Due some strange Word error (it sometimes repeat keystrokes for some strange reason) we had to move some of our Word interaction code to separate thread. But this lead us to another problem. It seems that the separate thread trying to load interop assemblies based on information in registry. And registry often contains wrong information. For example, if user install and then remove Office 2013, it doesn't clear PIA registry reference:
http://stackoverflow.com/questions/13722345/calling-com-object-from-sta-thread-cause-type-e-libnotregistered-on-some-machine
I tried to create my own interop assemblies with tlbimp, but without success.
Then I found your project and it helps. :)
But then came memory leaks. We didn't use Marshal.ReleaseCOMobject, relying on destructors of RCW that dispose comobjects for us, and this worked fine. But with netoffice we have to explicitly call Dispose. This is a lot of work to find all COM-object usages (thousands of lines of code), add Dispose and debug it. Also, debug disposes child objects, that is sometimes very inconvient for us. For example, we use Range.Duplicate a lot. And if we dispose first copy of range it will dispose all duplicates. Right?
So we decide to try to add destructor to COMObject class and call release from there.
Feb 11, 2013 at 6:20 AM
And if we dispose first copy of range it will dispose all duplicates. Right?
not sure what you means with first copy. if you dispose the parent range object then all duplicates (childs in this case) was also diposed.
if you call dispose for a specific duplicate then all other duplicates was still alive. what i see is the netoffice idea of comproxy management with parent-child relations is may a problem here.

my suggestion:store a worksheet reference and use them as long you need. when its done call worksheet.Dispose() or worksheet.DisposeChildInstances() and all ranges/duplicates and so on are released too.

Sebastian
Feb 11, 2013 at 6:51 PM
Edited Feb 11, 2013 at 6:58 PM
Thank you for quick answers!

Our Word add-in processing text very intensively. For example, it scans text for changes by constantly moving through sentences in text and comparing them with cached text representation. We actively getting ranges from document, often getting them from another ranges with Next or Duplicate.
Something like this
Range x = GetSomehowFromDocument(_doc);
Range r = x.Next(WdUnits.wdSentence);
Range r2 = r.Duplicate;
And in some places it even works with text by char (with Next(WdUnits.wdCharacter).

So, if we call x.Dispose in Above example, it will release r and r2. Am I right? And while user is working with document we can't dispose and memory keep flooding.

I concluded that leaks can be caused by objects collected in lists and by unreleased COM-objects and did following:
  1. Removed COMObject.AddChildObject
  2. Removed Factory.AddObjectToList
  3. Added destructor
    ~COMObject()
    {
        ReleaseCOMProxy();
    }
    And it seems to work! Word process is no longer growing in memory even with infinite document scan (from separate thread, by the way).
    Initialize error faded when I added sources from NetOffice to my solution and referenced project that I needed (instead of referencing compiled dlls). I can't understand why.
Am I missing something? What can be consequences of those changes?
I am understanding that I am losing Dispose this way, but I don't need it anymore - GC is doing all work for me.
Factory.AddObjectToList and _globalObjectList needed only for DisposeAllCOMProxies?

I think, that if everything ok it would be the useful option for the next release - as some switch (like you did with threads).
Feb 12, 2013 at 8:15 AM
Edited Feb 12, 2013 at 8:15 AM
So, if we call x.Dispose in Above example, it will release r and r2. Am I right?
yes, absolutly.

Factory.AddObjectToList and _globalObjectList needed only for DisposeAllCOMProxies?
yes and for the situation you create an object, set an event trigger (workbook_open or anyone else) and use Dispose(false) to destroy the proxy but keep the event listener alive, in this case com proxy parameters from the trigger are stored here if you dont dispose them at the end.
you need to sign the source projects with the provided .snk files in latest source. let me explain: the NetOffice.Core looks for loaded Assemblies with specific keytokens at runtime in the current application domain to fetch wrapper type informations, create a wrapper class instance for correpsonding proxies and so on. for identification its use an embedded textfile(KeyFiles.txt) change the file at your will or use the given .snk file in latest source

i think its possible to create an option do deactivate the automatic management for the child proxies. (added to todo list)

Sebastian
Feb 12, 2013 at 8:34 AM
Thanks for the clarification!
I used my own snk-files for NetOffice assemblies, because I modify them.

I'll check event parameters, but I think they should work ok with destructors. Anyway, we use events only for top-level objects like Document and Application, which we don't need to dispose often.
Feb 22, 2013 at 6:52 AM
update: last source state includes bool NetOffice.Settings.EnableProxyManagement;

Sebastian
Feb 22, 2013 at 8:42 AM
Thanks! We will try it.
By far, destructor works for Office 2007 and 2010, but we still have some memory leaks with Office 2003. Trying to figure out what the problem is.