how to remove toolbar from normal.dot?

J

Jerry Nettleton

I'm writing a COM add-in and delete the toolbar and menu in the
"OnDisconnection()" method with code show below. How can I remove the
toolbar from "normal.dot" file? When I select "Tools, Templates and
Add-Ins..., Templates tab, Organizer..." button, the toolbar I deleted is
still listed in normal.dot even after restarting Word.

if (RemoveMode != ext_dm_HostShutdown)
{
hr = OnBeginShutdown(custom);
if (SUCCEEDED(hr) && (RemoveMode == ext_dm_UserClosed))
{
RemoveToolBar(m_strProductName);
RemoveMenuBar(_T("Tools"), m_strProductName);
}
}

I've also tried taking a look at the 'NormalTemplate' property but I didn't
find anything to get a list of items to search and then delete the one that
I created.:

CString str;
TemplatePtr spNormal = m_spApplication->NormalTemplate;
str.Format(_T("Normal Name = %s\n"), (TCHAR *) spNormal->Name);
OutputDebugString(str.GetString());


Thanks,
Jerry
 
P

Peter Huang [MSFT]

Hi

If you want to add the toolbar when the addin is loaded and unload it when
the addin is unloaded.
I think you may try to Add the Toolbar and CommandBarButton as temporary
and delete it at the end.

The last parameter of the Add method will tell Office to create it
temporarily.


=====================
Add method as it applies to the CommandBars object.

Creates a new command bar and adds it to the collection of command bars.
Returns a CommandBar object.

expression.Add(Name, Position, MenuBar, Temporary)
expression Required. An expression that returns a CommandBars object.

Name Optional Variant. The name of the new command bar. If this argument
is omitted, a default name is assigned to the command bar (such as Custom
1).

Position Optional Variant. The position or type of the new command bar.
Can be one of the MsoBarPosition constants listed in the following table.

Constant Description
msoBarLeft, msoBarTop, msoBarRight, msoBarBottom Indicates the left, top,
right, and bottom coordinates of the new command bar
msoBarFloating Indicates that the new command bar won't be docked
msoBarPopup Indicates that the new command bar will be a shortcut menu
msoBarMenuBar Macintosh only

MenuBar Optional Variant. True to replace the active menu bar with the
new command bar. The default value is False.

Temporary Optional Variant. True to make the new command bar temporary.
Temporary command bars are deleted when the container application is
closed. The default value is False.

====================
Add method as it applies to the CommandBarControls object.

Creates a new CommandBarControl object and adds it to the collection of
controls on the specified command bar.

expression.Add(Type, Id, Parameter, Before, Temporary)
expression Required. An expression that returns a CommandBarControls
object.

Type Optional Variant. The type of control to be added to the specified
command bar. Can be one of the following MsoControlType constants:
msoControlButton, msoControlEdit, msoControlDropdown, msoControlComboBox,
or msoControlPopup.

Id Optional Variant. An integer that specifies a built-in control. If the
value of this argument is 1, or if this argument is omitted, a blank custom
control of the specified type will be added to the command bar.

Parameter Optional Variant. For built-in controls, this argument is used
by the container application to run the command. For custom controls, you
can use this argument to send information to Visual Basic procedures, or
you can use it to store information about the control (similar to a second
Tag property value).

Before Optional Variant. A number that indicates the position of the new
control on the command bar. The new control will be inserted before the
control at this position. If this argument is omitted, the control is added
at the end of the specified command bar.

Temporary Optional Variant. True to make the new control temporary.
Temporary controls are automatically deleted when the container application
is closed. The default value is False.


=============================
Delete method as it applies to the CommandBar, Script, Scripts, and
Signature objects.

Deletes the specified object from the collection.

expression.Delete
expression Required. An expression that returns one of the above objects.

==============================
Delete method as it applies to the CommandBarButton, CommandBarComboBox,
CommandBarControl, and CommandBarPopup objects.

Deletes the specified object from its collection.

expression.Delete(Temporary)
expression Required. An expression that returns one of the above objects.

Temporary Optional Variant. True to delete the control for the current
session. The application will display the control again in the next session.


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
K

Ken Slovak - [MVP - Outlook]

Hi Peter,

In my experience with Word it doesn't honor the Temporary setting. You have
to explicitly delete any command bar/button you've created.
 
J

Jerry N

Yes, everything was deleted (command bar, tools menu item, and help menu
items) and the toolbar is still listed in 'normal.dot'.

Take a look at the 'Organizer...' window (Tools -> Templates and Add-Ins ->
Organizer -> Toolbars tab).
 
K

Ken Slovak - [MVP - Outlook]

You have to set the CustomizationContext.Saved property to True to prevent
normal.dot from persisting things even after they are deleted.
 
P

Peter Huang [MSFT]

Hi Jerry,

Based on my test with the code below, I will create a toolbar and delete it
at shutdown, I perhaps did not make it more clear.

Based on my test, if I select create button on connection, I did not see
the toolbar at the 'Organizer...' window (Tools -> Templates and Add-Ins ->
Organizer -> Toolbars tab). I just can see it on the toolbar. If I select
no, when I close and restart winword, then the toolbar will not show just
as I did not load the addin.

You may have a try.
Also I think you may Ken's suggestion about CustomizationContext

Public Class Connect
Implements Extensibility.IDTExtensibility2
'Dim applicationObject As Object
'Dim addInInstance As Object
Dim wdApp As Word.Application
Dim cmBar As Office.CommandBar
Dim cbb As Office.CommandBarButton
Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnBeginShutdown
If Not cbb Is Nothing Then
cbb.Delete()
End If
If Not cmBar Is Nothing Then
cmBar.Delete()
End If
End Sub
Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnAddInsUpdate
End Sub
Public Sub OnStartupComplete(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnStartupComplete
Debug.WriteLine("OnStartupComplete")
If MsgBox("Do you want Create Toolbar?", MsgBoxStyle.YesNo) =
MsgBoxResult.Yes Then

cmBar = wdApp.CommandBars.Add("Test", , , True)
cmBar.Visible = True
cmBar.Position = MsoBarPosition.msoBarTop
cbb =
cmBar.Controls.Add(Office.MsoControlType.msoControlButton, , , , True)
cbb.Caption = "Test"
cbb.FaceId = 17
Debug.WriteLine("Create Toolbar Complete")
End If

End Sub
Public Sub OnDisconnection(ByVal RemoveMode As
Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnDisconnection
End Sub
Public Sub OnConnection(ByVal application As Object, ByVal connectMode
As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom
As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
wdApp = DirectCast(application, Word.Application)
Debug.WriteLine("OnConnection")
'applicationObject = application
'addInInstance = addInInst
End Sub

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jerry N

I tried to use the "CustomizationContext.Saved" property but I'm not sure how
to use it (IDispatchPtr _Application::GetCustomizationContext ( );).

But while testing one more possibility, I discovered that I had forgotten to
remove a Help menu item. When I removed it, the add-in entry in the
"normal.dot" file was automatically deleted, too.

So it looks like this issue is resolved. The add-in entry was still present
because not everything was removed properly.

Thanks,
Jerry
 
J

Jerry N

Let's reopen this issue. After a few more tests, I found out that the add-in
entry only get removed if load and unload the COM add-in w/o exiting Word.
If I load the add-in, exit Word, restart Word, and unload the add-in, then
the add-in stays in the normal.dot file. How can I clean up and delete this
entry?

Thanks,
Jerry
 
P

Peter Huang [MSFT]

Hi

Based on my understanding, the addin entry you means is the toolbar which
will be created during the OnStartupComplete and remove in the
OnBeginShutDown.
If so, based on my test, I can not reproduce the problem.
Here is my reproduce steps.
1. Open the word, I will select Yes to create the toolbar Button and I will
see the toolbar
2. Unload the Addin, the toolbar has not be removed so far.
3. Close the Word
4. Open the Word and the Addin is not loaded
5. so far I did not see the popup dialog about if I want to load the addin
because the addin is not loaded, and the Toolbar did not apprear.

You may perform the steps above to have a test.
If you still did not work, I think you may try to add the code in the
OnDisconnection method.
Public Sub OnDisconnection(ByVal RemoveMode As
Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnDisconnection
Debug.WriteLine("OnDisconnection")
If Not cbb Is Nothing Then
cbb.Delete()
End If
If Not cmBar Is Nothing Then
cmBar.Delete()
End If
End Sub



Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jerry Nettleton

Do you have "LoadBehavior = 0x03" (typical setting)? I'll follow the steps
later today...
 
J

Jerry Nettleton

I followed these steps and still have an entry in the normal.dot file. Could
you send me your sample program? If not, could you sent code snipets (I'll
could create a new add-in and then add the snipets)?

In the documentation, it hasn't been clear that command bars should be
created in OnStartupComplete() and removed in OnBeginShutdown(). I changed
my code so that it follows this recommendation. No changes for this problem.
The normal.dot file still has an add-in reference when I restart Word.

Is there anyway to dump/enumerate any information about my toolbar in the
normal.dot file? Perhaps I haven't deleted something. Or perhaps Word left
something in there by accident (incomplete garbage collection).

How do I use the 'CustomizationContext' property? Any sample code for it?

Thanks,
Jerry
 
K

Ken Slovak - [MVP - Outlook]

Try this just after you create your buttons and then again just after you
delete them (the seconds pass is to avoid the prompt to save normal.dot if
the user has that set):

Set CustomizationContext = oDoc.AttachedTemplate
CustomizationContext.Saved = True
oWord.ActiveDocument.AttachedTemplate.Saved = True
 
J

Jerry Nettleton

Here's a summary of what I found:

1. start Word

2. verify no entry in normal.dot

3. enable add-in
CAddin::OnConnection = AfterStartup
CAddin::OnStartupComplete
CAddin::OnAddInsUpdate

4. disable add-in
CAddin::OnDisconnection = UserClosed
CAddin::OnBeginShutdown

5. verify no entry in normal.dot

6. re-enable add-in
CAddin::OnConnection = AfterStartup
CAddin::OnStartupComplete
CAddin::OnAddInsUpdate

7. exit Word
CAddin::OnBeginShutdown
CAddin::OnDisconnection = HostShutdown

8. start Word
CAddin::OnConnection = Startup
CAddin::OnAddInsUpdate
CAddin::OnStartupComplete

9. found entry in normal.dot

10. disable add-in
CAddin::OnDisconnection = UserClosed
CAddin::OnBeginShutdown

11. entry still in normal.dot

12. exit Word
13. start Word
14. command bar still present, add-in still disabled (not checked), entry
still in normal.dot

15. click on command bar button
CAddin::OnConnection = AfterStartup
CAddin::OnStartupComplete
CAddin::OnAddInsUpdate

16. exit Word
CAddin::OnBeginShutdown
CAddin::OnDisconnection = HostShutdown

Hope this helps,
Jerry
 
P

Peter Huang [MSFT]

Hi

Yes, I have enable the LoadBehavior to 3.
Here is the whole file of my Addin in VB.NET.
Imports Microsoft.Office.Core
imports Extensibility
imports System.Runtime.InteropServices
Imports Word = Microsoft.Office.Interop.Word
Imports Office = Microsoft.Office.Core
#Region " Read me for Add-in installation and setup information. "
' When run, the Add-in wizard prepared the registry for the Add-in.
' At a later time, if the Add-in becomes unavailable for reasons such as:
' 1) You moved this project to a computer other than which is was
originally created on.
' 2) You chose 'Yes' when presented with a message asking if you wish to
remove the Add-in.
' 3) Registry corruption.
' you will need to re-register the Add-in by building the
WordAddin_CommandBarsSetup project
' by right clicking the project in the Solution Explorer, then choosing
install.
#End Region

<GuidAttribute("769FF42D-B7CA-45C3-8ACB-46EB3E54700C"),
ProgIdAttribute("WordAddin_CommandBars.Connect")> _
Public Class Connect
Implements Extensibility.IDTExtensibility2
'Dim applicationObject As Object
'Dim addInInstance As Object
Dim wdApp As Word.Application
Dim cmBar As Office.CommandBar
Dim cbb As Office.CommandBarButton
Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnBeginShutdown
Debug.WriteLine("OnBeginShutdown")
If Not cbb Is Nothing Then
cbb.Delete()
End If
If Not cmBar Is Nothing Then
cmBar.Delete()
End If
End Sub
Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnAddInsUpdate
Debug.WriteLine("OnAddInsUpdate")
End Sub
Public Sub OnStartupComplete(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnStartupComplete
Debug.WriteLine("OnStartupComplete")
If MsgBox("Do you want Create Toolbar?", MsgBoxStyle.YesNo) =
MsgBoxResult.Yes Then

cmBar = wdApp.CommandBars.Add("Test", , , True)
cmBar.Visible = True
cmBar.Position = MsoBarPosition.msoBarTop
cbb =
cmBar.Controls.Add(Office.MsoControlType.msoControlButton, , , , True)
cbb.Caption = "Test"
cbb.FaceId = 17
Debug.WriteLine("Create Toolbar Complete")
End If

End Sub
Public Sub OnDisconnection(ByVal RemoveMode As
Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnDisconnection
Debug.WriteLine("OnDisconnection")
If Not cbb Is Nothing Then
cbb.Delete()
End If
If Not cmBar Is Nothing Then
cmBar.Delete()
End If
End Sub
Public Sub OnConnection(ByVal application As Object, ByVal connectMode
As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom
As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
wdApp = DirectCast(application, Word.Application)
Debug.WriteLine("OnConnection")
'applicationObject = application
'addInInstance = addInInst
End Sub
End Class

To ensure the unload of toolbar, you may try to delete the cbb and cmBar in
OnDisconnection.
Also I think you may try make sure if the Two Delete method is called.(e.g.
add some trace code before and after the delete code)
Also you may try to see if the COM reference to the cbb and cmBar has been
released correctly.

You may have a try, if you still have any concern, can you send a reproduce
sample of your code, so that I can try to reproduce.
You can reach me via removing the "online" from my email address.

Thanks for your efforts!

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jerry Nettleton

It seems to me that you need to emulate a real application a little better in
your test program. I have several comments/questions:

- In OnConnection, you don't check ConnectMode:
if (ConnectMode != ext_cm_Startup)
hr = OnStartupComplete(custom);

- In OnDisconnection, you don't check RemoveMode:
if (RemoveMode != ext_dm_HostShutdown)
hr = OnBeginShutdown(custom);

- In OnBeginShutdown and OnDisconnection, you delete the command bar in both
methods w/o setting "cbb = Nothing".
A. Why are trying to delete in both places? Does "cbb = Nothing" happen
automatically?
B. With bugs reported in this article
(http://support.microsoft.com/default.aspx?scid=kb;en-us;230876) for Word
2000/2002/2003, why are you deleting the command bar using a previous
reference (instead of using FindControl)?

If you make a few changes, then perhaps you will be able to reproduce the
problem.

Thanks,
Jerry
 
J

Jerry Nettleton

I add this code to OnStartupComplete and OnBeginShutdown where the toolbar
and menus items are created and removed (but found no improvement):

RemoveToolBarPopup(_T("Text"), m_strProductName);
_variant_t vTemplate = m_spApplication->ActiveDocument->GetAttachedTemplate);
if (vTemplate.vt == VT_DISPATCH)
{
TemplatePtr spTemplate = vTemplate.pdispVal;
if (spTemplate != NULL)
spTemplate->Saved = VARIANT_FALSE;
}

So I implemented the ActiveDocuement part, how did you get a reference to
'oDoc'? I need to add code for:

Set CustomizationContext = oDoc.AttachedTemplate
CustomizationContext.Saved = True

Thanks,
Jerry
 
P

Peter Huang [MSFT]

Hi Jerry,

I have tried to check the ConnectMode and RemoveMode but it is strange that
I still can not reproduce the problem.
The below is the code.

Because my code is for demo purpose, it is not a valid software, so I did
not make it very formal, I am sorry for that.

For cbb issue, in .NET, the GC will try to release the managed reference.

I think you need to pay attention to two points.
1. Add the Toolbar temporarily
2. Call the Delete method when the Addin is going to Disconnection/Unload.

Imports Microsoft.Office.Core
imports Extensibility
imports System.Runtime.InteropServices
Imports Word = Microsoft.Office.Interop.Word
Imports Office = Microsoft.Office.Core
#Region " Read me for Add-in installation and setup information. "
' When run, the Add-in wizard prepared the registry for the Add-in.
' At a later time, if the Add-in becomes unavailable for reasons such as:
' 1) You moved this project to a computer other than which is was
originally created on.
' 2) You chose 'Yes' when presented with a message asking if you wish to
remove the Add-in.
' 3) Registry corruption.
' you will need to re-register the Add-in by building the
WordAddin_CommandBarsSetup project
' by right clicking the project in the Solution Explorer, then choosing
install.
#End Region

<GuidAttribute("769FF42D-B7CA-45C3-8ACB-46EB3E54700C"),
ProgIdAttribute("WordAddin_CommandBars.Connect")> _
Public Class Connect
Implements Extensibility.IDTExtensibility2
Dim wdApp As Word.Application
Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnBeginShutdown
Dim cmBar As Office.CommandBar
Dim cbb As Office.CommandBarButton
Debug.WriteLine("OnBeginShutdown")
Try
cmBar = wdApp.CommandBars("Test")
cbb = cmBar.FindControl(, , "TestTag", , )
Catch ex As Exception
Debug.WriteLine(ex.ToString())
End Try
If Not cbb Is Nothing Then
cbb.Delete()
End If
If Not cmBar Is Nothing Then
cmBar.Delete()
End If
Marshal.ReleaseComObject(cbb)
Marshal.ReleaseComObject(cmBar)
cbb = Nothing
cmBar = Nothing
End Sub
Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnAddInsUpdate
Debug.WriteLine("OnAddInsUpdate")
End Sub
Public Sub OnStartupComplete(ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnStartupComplete
Debug.WriteLine("OnStartupComplete")
Dim cmBar As Office.CommandBar
Dim cbb As Office.CommandBarButton
If MsgBox("Do you want Create Toolbar?", MsgBoxStyle.YesNo) =
MsgBoxResult.Yes Then
cmBar = wdApp.CommandBars.Add("Test", , , True)
cmBar.Visible = True
cmBar.Position = MsoBarPosition.msoBarTop
cbb =
cmBar.Controls.Add(Office.MsoControlType.msoControlButton, , , , True)
cbb.Caption = "TestBar"
cbb.FaceId = 17
cbb.Tag = "TestTag"
Debug.WriteLine("Create Toolbar Complete")
End If
Marshal.ReleaseComObject(cbb)
Marshal.ReleaseComObject(cmBar)
cbb = Nothing
cmBar = Nothing
End Sub
Public Sub OnDisconnection(ByVal RemoveMode As
Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements
Extensibility.IDTExtensibility2.OnDisconnection
Debug.WriteLine("OnDisconnection")
If Not RemoveMode = ext_DisconnectMode.ext_dm_HostShutdown Then
OnBeginShutdown(custom)
End If
End Sub
Public Sub OnConnection(ByVal application As Object, ByVal connectMode
As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom
As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
wdApp = DirectCast(application, Word.Application)
Debug.WriteLine("OnConnection")
If Not connectMode = ext_ConnectMode.ext_cm_Startup Then
OnStartupComplete(custom)
End If
End Sub
End Class


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
K

Ken Slovak - [MVP - Outlook]

In the case of the code snippet I showed oDoc was derived from the WordMail
email window in Outlook. In the case of a pure Word application it could be
from Application.ActiveDocument.
 
J

Jerry Nettleton

Then what I already coded should have worked. This suggestion still didn't
work.

FYI, I noticed this exception while in the "GetActiveDocument()' wrapper so
it appears that the ActiveProperty isn't valid in the OnBeginShutdown event.

First-chance exception at 0x77e738b2 in WINWORD.EXE: Microsoft C++
exception: _com_error @ 0x0012f120.
OnBeginShutdown: hr = 0x800A1098, error message = 'Unknown error 0x800A1098'


I'll looking for another solution and will let you know what I find...

Jerry
 
J

Jerry Nettleton

It looks like I got something working now. I made sure that all Add() calls
explicitly set the 'Temporary' parameter to TRUE. Now the add-in doesn't
even show up in the Organizer window. I'll do some more testing but it's
looks good for now.

FYI, the 'CustomizationContext.Save = true' didn't make any difference. I
removed the code now and saw no change.

Sure would great if this newsgroup was archived beyond 10/2004. I'm sure
this problem has come up before...

Thanks for your help,
Jerry
 

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