COM Exception

N

Nicu

Hello!

I'm developing an addin for Microsoft Office 2003, using VS 2005 and VSTO
2005SE with all the updates. I got random, so weird, an exception that says:

Unable to cast COM object of type
'Microsoft.Office.Interop.Word.DocumentClass' to interface type
'Microsoft.Office.Interop.Word._Document'. This operation failed because the
QueryInterface call on the COM component for the interface with IID
'{0002096B-0000-0000-C000-000000000046}' failed due to the following error:
The application called an interface that was marshalled for a different
thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).

I searched over the internet but I couldn't find anything to help. I'm
releasing the COM objects used at ThisAddIn_Shutdown, with the following
lines of code:

private Office.CommandBarPopup foundMenu;
private Office.CommandBarPopup newMenuBar;

if (foundMenu != null) Marshal.ReleaseComObject(foundMenu);
if (newMenuBar != null) Marshal.ReleaseComObject(menuBar);

I do this even when I try to remove the menu bar:

private void RemoveMenuBar()
{
object temporary = true;

try
{
// If the found menu exists already
if (foundMenu != null) Marshal.ReleaseComObject(foundMenu);

foundMenu = (CommandBarPopup)
this.Application.CommandBars.ActiveMenuBar.FindControl(MsoControlType.msoControlPopup, missing, menuTag, true, true);

if (foundMenu != null)
{
foundMenu.Delete(temporary);
}
}
catch (Exception ex)
{
OfficeLibraryUtils.logger.Error(ex.Message);
OfficeLibraryUtils.HandleException(ex);
}
}

I read about the [MTAThread] over the internet. I tried to use it, but I
didn't get rid of this mighty weird exception.

What am I doing wrong? Please help. Hope someone can light my problem, it
will be very appreciated!

Thanks in advance,
Nicu
 
N

Nicu

I could add that the exception occurs when I try to access a custom menu
added by me. I add a menu entry this way:

//button Save As...
btnSaveAs =
(Office.CommandBarButton)newMenuBar.Controls.Add(
Office.MsoControlType.msoControlButton, missing,
missing, 1, true);
btnSaveAs.Style =
Office.MsoButtonStyle.msoButtonIconAndCaption;
btnSaveAs.Caption = "Save &As...";
btnSaveAs.FaceId = 0;
btnSaveAs.Tag = "saveAsButtonTag";
btnSaveAs.Visible = true;
btnSaveAs.Click += new
Office._CommandBarButtonEvents_ClickEventHandler(btnSaveAs_Click);

And the click procedure looks like this:

private void btnSaveAs_Click(Office.CommandBarControl ctrl, ref bool cancel)
{
try
{
// Try to do whatever

}
catch (Exception ex)
{
// Handle exception here
}
}
 
C

Cindy M.

Hi =?Utf-8?B?TmljdQ==?=,
I'm developing an addin for Microsoft Office 2003, using VS 2005 and VSTO
2005SE with all the updates. I got random, so weird, an exception that says:

Unable to cast COM object of type
'Microsoft.Office.Interop.Word.DocumentClass' to interface type
'Microsoft.Office.Interop.Word._Document'. This operation failed because the
QueryInterface call on the COM component for the interface with IID
'{0002096B-0000-0000-C000-000000000046}' failed due to the following error:
The application called an interface that was marshalled for a different
thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).

I searched over the internet but I couldn't find anything to help. I'm
releasing the COM objects used at ThisAddIn_Shutdown, with the following
lines of code:
DON'T use Marshal.ReleaseComObject in your Add-in code. You shouldn't need it.
VSTO should take care of all of this for you, at the proper time - that's part
of the package. Go ahead and set any class-level object to null, if you wish,
but don't try to do any clean-up at the RCW level.

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or reply
in the newsgroup and not by e-mail :)
 
N

Nicu

Hi!

Thanks for the reply. I didn't use ReleaseCOMObjects in the past but I was
still getting the same weird, random exception:
'Microsoft.Office.Interop.Word.DocumentClass' to interface type
'Microsoft.Office.Interop.Word._Document'. This operation failed because the
QueryInterface call on the COM component for the interface with IID
'{0002096B-0000-0000-C000-000000000046}' failed due to the following error:
The application called an interface that was marshalled for a different
thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).

I'm working with a web service, sending and opening documents from Word. I'm
using authentication for users (tokenprofile) and this is done on a different
thread. Could this be the cause of exception? If that, why is random? Is
there any attributes that I must set (as [MTAThread] or [STAThread])? I'm
also using a CommandQueue pattern. Should I add to ExecuteCommand one of
these attributes? I read over the internet that MS Office addins should be
single threaded (STA). Any ideeas? If you have any other questions about the
code, I could post it gladly.

Thanks!
Nicu
 
C

Cindy M.

Hi Nicu,

I'm not sure whether your most recent response doesn't confuse me more
than help... :)
I read over the internet that MS Office addins should be
single threaded (STA).
Yes. Office is (and must be) single threaded. Although your application
can use multi-threading for things done outside the Office interface, such
as querying a web service (you'd just have to watch out for
synchronization issues).

I'd like to go back a step and ask you how you declare the objects you use
with the CommandBars. At what level is, for example, btnSaveAs declared?
Within the method, at class level, something else?

If you start a new solution with commandbar buttons and have the Click
events do something simple (MessageBox.Show), do things work correctly? If
yes, start adding things like you're doing in the "real" add-in and see
what triggers the problem.

You may want to take this to the VSTO forum:
http://social.msdn.microsoft.com/Forums/en-US/vsto/threads/. Geoff Darst
[MSFT] is particularly savvy when it comes to intricacies like you're
using.

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or
reply in the newsgroup and not by e-mail :)
 
N

Nicu

Hello!

Thanks again for your reply! The button is declared in ThisAddIn.cs, class
level:

public partial class ThisAddIn
{

#region variables

private Office.CommandBarButton btnSaveAs;
//...etc

#endregion
}

Than I have a function for adding the menu and one for removing it. In the
function AddMenuBar I have this:

try
{
int menuPosition = 0;
object missing = Type.Missing;
menuBar = this.Application.CommandBars.ActiveMenuBar;
menuPosition = menuBar.Controls.Count;
newMenuBar = (Office.CommandBarPopup)menuBar.Controls.Add(
//temporary menu
Office.MsoControlType.msoControlPopup, missing, missing,
menuPosition, true);

if (newMenuBar != null)
{
newMenuBar.Caption = "&MyMenuCaptionHere";
newMenuBar.Tag = menuTag;

btnSaveAs =
(Office.CommandBarButton)newMenuBar.Controls.Add(
Office.MsoControlType.msoControlButton, missing,
missing, 1, true);
btnSaveAs.Style =
Office.MsoButtonStyle.msoButtonIconAndCaption;
btnSaveAs.Caption = "Save &As...";
btnSaveAs.FaceId = 0;
btnSaveAs.Tag = "saveAsButtonTag";
btnSaveAs.Visible = false;
btnSaveAs.Click += new
Office._CommandBarButtonEvents_ClickEventHandler(btnSaveAs_Click);

newMenuBar.Visible = true;
}
catch(Ex....)
{}

The function that handles the click event for the btnSaveAs is this one:
private void btnSaveAs_Click(Office.CommandBarControl ctrl, ref bool cancel)
{
try
{
// Try to work here.
}
catch (Exception ex)
{
// Log the exception here.
}
}

I made a new solution and everyhing works fine. I add the fact that even my
project with the save as button works fine, but only sometimes that error
shows up, not always (for instance, after an amount of time of
"communicating" with the webservice: sending/opening documents).

Excuse my bad english and "the way of explaining things" :)...
Thanks for your help, I will try to post it overthere. Your kindness and
patience are much appreciated!

Regards,
Nicu
 
N

Nicu

Hey again!

I forgot to say that I'm enabling and disabling menus on the fly in the same
application :) - "details, isn't it?", yeah, I know...

I just want to post the solution I found, it works OK:

public void EnableOrDisableWordMenuButtons(string uniqueMenuTag, bool enabled)
{
// Find the popup menu bar here.
Microsoft.Office.Core.CommandBarPopup menuBar =

(Microsoft.Office.Core.CommandBarPopup)app.CommandBars.FindControl(missing,
missing,
menuTagHere,
missing);

// If we found it, then try searching for the button with the
given tag:
if (menuBar != null)
{
// Find the menu with the given tag here...
Microsoft.Office.Core.CommandBarButton button =
(Microsoft.Office.Core.CommandBarButton)menuBar.CommandBar.FindControl(missing, missing, uniqueMenuTag, missing, missing);

// If the button was found...
if (button != null)
{
// Disable found menu here.
button.Enabled = enabled;
}

}
}
 
N

Nicu

Me again... Hi all!

The "darkest exception" is here again, same:

Unable to cast COM object of type
'Microsoft.Office.Interop.Word.DocumentClass' to interface type
'Microsoft.Office.Interop.Word._Document'. This operation failed because the
QueryInterface call on the COM component for the interface with IID
'{0002096B-0000-0000-C000-000000000046}' failed due to the following error:
The application called an interface that was marshalled for a different
thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).

The code I posted above seems didn't make it "dissappear". I read about this
exception on KB, and it says about CoMarshalInterThreadInterfaceInStream()
and CoGetInterfaceAndReleaseStream() but I searched over the internet and I
couldn't find something that could help me. I'm using C# so I'll need to
invoke this functions using WinAPI but where in my code I don't know exactly.

Any hints, ideeas or links would be very helpful!

Thanks,
Nicu
 
N

Nicu

If this helps, the exception is raised here:

at Microsoft.Office.Interop.Word.DocumentClass.get_FullName()
at WordAddIn1.OpenDocuments.IsOpenedFromWeb(Document document)
at WordAddIn.ThisAddIn.btnSendInWeb_Click(CommandBarButton ctrl, Boolean&
cancel)
 
C

Cindy M.

Hi Nicu,
at Microsoft.Office.Interop.Word.DocumentClass.get_FullName()
at WordAddIn1.OpenDocuments.IsOpenedFromWeb(Document document)
at WordAddIn.ThisAddIn.btnSendInWeb_Click(CommandBarButton ctrl, Boolean&
cancel)
I'm afraid I've lost the plot a bit, here, but...

You shouldn't be using the DocumentClass in your code, only Document. So if
you're declaring a document object:
Word.Document Doc;

Then you'll have access to the FullName property, directly:
Doc.FullName;

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or reply
in the newsgroup and not by e-mail :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top