BUG: NullReferenceException Is Thrown by an Unmanaged Object After IVsaEngine.Reset (319799)
The information in this article applies to:
- Microsoft Visual Studio for Applications SDK 1.0
This article was previously published under Q319799 SYMPTOMS
A managed Visual Studio for Applications (VSA) host creates an instance of an unmanaged object by using a Runtime Callable Wrapper (RCW). The host adds the unmanaged object as an AppGlobal object, by using IVsaEngine.Items.CreateItem and IVsaSite.GetGlobalInstance. When the host calls IVsaEngine.Reset, the RCW loses its connection to the unmanaged object. This causes a System.NullReferenceException error if the host tries to make a call on the RCW.
CAUSE
When an unmanaged VSA host adds an unmanaged AppGlobal object to the VSA engine, a RCW is automatically created for the object. A COM reference to the unmanaged object is maintained by the RCW until it is cleaned up by the Microsoft .NET garbage collector. Because .NET uses a "lazy" garbage-collection scheme, this reference may take some time to be released. This may prevent the unmanaged host application from quitting cleanly.
To resolve this issue, the IVsaEngine.Reset method calls Marshal.ReleaseComObject on any unmanaged AppGlobal objects that have been added to the engine. This decrements the reference count on the COM object and permits the host to quit cleanly. Unfortunately, this resolution does not work in the case of a managed VSA host that uses unmanaged AppGlobal objects. Because the managed host maintains the RCW for the unmanaged AppGlobal object, it is incorrect for VSA to call Marshal.ReleaseComObject.
RESOLUTION
There are two possible resolutions.
The first resolution is to write a managed wrapper class for the AppGlobal object, and then to pass that wrapper class to VSA. Because the custom wrapper class is not an RCW, VSA does not try to release it. This is the better solution, because you can also add .NET attributes (such as security attributes) if you must.
If you cannot write a custom wrapper class for your object, the second resolution is to take advantage of the manner in which RCW referencing works to keep an artificial reference count on the object that you give to VSA. When a COM interface is passed to managed code, the .NET runtime looks through the existing RCWs to determine if there is already an RCW for that object. If it finds that a RCW already exists, it adds a reference to the RCW instead of creating a new RCW. When Marshal.ReleaseComObject is called during the reset, the RCW is decremented and is not "zombied" for garbage collection.
To do this, add a method to your COM object that returns an interface pointer for that same object again. Pass this reference to the VSA engine in IVsaSite.GetGlobalInstance. When you call IVsaEngine.Reset, this additional reference is decremented, but the RCW keeps its connection to the unmanaged object.
STATUSMicrosoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article. REFERENCES
For more information about Visual Studio for Applications, visit the following MSDN Web site:
Modification Type: | Major | Last Reviewed: | 5/16/2002 |
---|
Keywords: | kbbug kbDSupport KB319799 |
---|
|