VSTO Solution: Prompting to Save Normal.dotm


When you are automating Microsoft Word you may get a message similar to the following that appears when trying to Quit() the application:

This file is in use by another application or user.

(C:\Users\…\Normal.dotm

image

This is followed by several more prompts, like the Save As dialog and then this:

Changes have been made that affect the global template, Normal.dotm. Do you want to save those changes?

image

Typically, this occurs when there are multiple instance of WINWORD.EXE in memory. The problem occurs when one of them does something to the application (like changing a setting, macro or style) and ultimately causes those changes to be saved to the normal template. Typically, the first instance that closes locks the file and this causes the subsequent instances to be flagged to prompt you to save the changes.

This issue has been detailed here:

http://support.microsoft.com/kb/918064

Well, this is an issue I encounter often in the field and I have created some code to help with this situation:

/// <summary>
/// The deactivate event is called before the application exits.
/// We cannot determine when we exit or not (specifically), but anytime
/// this event fires, we locate the normal template and flip the flag
/// in order to prevent the dreaded "Normal needs to be saved" prompt.
/// </summary>
/// <param name="Doc"></param>
/// <param name="Wn"></param>
void Application_WindowDeactivate(Word.Document Doc, Word.Window Wn)
{
    try
    {
        object objectIndex = 0;
        // loop through all the loaded templates
        for (int idx = 1; idx <= Application.Templates.Count; idx++)
        {
            objectIndex = idx;
            Word.Template t = Application.Templates.get_Item(
                    ref objectIndex);
            // look for normal
            if (t.Name.ToLower().Contains("normal.dotm"))
            {
                // found it – set the flag and leave the loop
                t.Saved = true;
                break;
            }
        }
    }
    catch { } // something bad happened – but we will ignore it
}

Essentially, you attach to the Window Deactivate event and look for the Normal.dotm in the Templates collection and set the flag to saved. We have to place this in the Deactivate event because the Normal.dotm prompt occurs before your add-in unload event. Therefore, on deactivate just before the application quits, the Normal template flag is flipped to prevent the prompt. Here is how you hook up this event:

// attach to the Window Deactivate event in Word
Application.WindowDeactivate += new Microsoft.Office.Interop.
        Word.ApplicationEvents4_WindowDeactivateEventHandler(
            Application_WindowDeactivate);

4 thoughts on “VSTO Solution: Prompting to Save Normal.dotm

  1. I am having the exact same issue – we have users who work in many docs simultaneously, but do not make changes to normal template.

    Could you quickly explain how to use the above code? Would I compile it in VSTO as an Word add-in? Or some kind of automacro? (I am relatively inexperienced in development)

    Thank you,
    Jack

  2. IN VB .net it is simple:

    Dim oWord As Word.Application = Nothing

    Private Sub Word_WindowDeactivate(ByVal Doc As Word.Document, ByVal Wn As Word.Window)
    Try
    For Each T As Word.Template In oWord.Templates
    If T.Name.ToLower().Contains(“normal.dotm”) Then
    T.Saved = True
    Exit Sub
    End If
    Next T
    Catch ex As Exception
    End Try
    End Sub

    and in your function:

    oWord = New Word.Application
    AddHandler oWord.WindowDeactivate, AddressOf Word_WindowDeactivate

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s