The new readonly balloon in Word closes my custom modal dialog of a VSTO Addin unexpectedly
Our development teams have spent several days trying to fix the following issue in Microsoft Word 365 (Microsoft® Word voor Microsoft 365 MSO (Versie 2301 Build 16.0.16026.20002) 32 bits).
We have a VSTO addin which should show a modal dialog when a user opens document which is linked to our document management system to ask if the user wants to open a newer version or just want to open the current document.
This dialog should only be closed by the user, but Word is closing this window unexpectedly when it is a readonly document.
To post this question I've boiled down the problem to a simple VSTO addin to demonstrate the issue.
Steps to reproduce:
- Create a new VSTO C# addin for Microsoft Word.
- Put in the following code:
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
AddinManager.EnsureSynchronizationContext();
Globals.ThisAddIn.Application.DocumentOpen += application_DocumentOpen;
}
private async void application_DocumentOpen(Word.Document Doc) => await System.Threading.Tasks.Task.Run(() => showDialog());
private void showDialog()
{
doSomethingImportantStuffLikeCallingARESTAPIOrSomethingLikeThat();
AddinManager.RunActionOnUIThread(() =>
{
// Globals.ThisAddIn.Application.Activate(); // Workaround: by reactivating the application the closing of the form
var form = new Form1();
form.ShowDialog();
});
}
private static void doSomethingImportantStuffLikeCallingARESTAPIOrSomethingLikeThat() => Thread.Sleep(500);
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
- Add an AddInManager.cs with the following code:
public class AddinManager
{
public static SynchronizationContext UISynchronizationContext { get; set; }
public static void RunActionOnUIThread(Action uiAction)
{
if (UISynchronizationContext == null)
throw new InvalidOperationException("Het is niet mogelijk om een actie uit te voeren op de UI thread indien de UISynchronizationContext nog niet gezet is. Zet de UISynchronizationContext in de main form van de applicatie.");
else
{
UISynchronizationContext.Send(d =>
{
//This executes on the ui thread
uiAction();
}, null);
}
}
/// <summary>
/// Because a VSTO add-in itself does not have a main window, a form is created here and opened briefly. This creates the WindowsFormsSynchronizationContext and can be placed in the ApplicationHost.
/// This is used to perform actions on the UI from a background thread. The form itself will never be visible to the user.
/// </summary>
public static void EnsureSynchronizationContext()
{
WindowsFormsSynchronizationContext.AutoInstall = true;
var form = new Form();
form.Load += Form_Load;
form.Show();
UISynchronizationContext = WindowsFormsSynchronizationContext.Current;
}
private static void Form_Load(object sender, EventArgs e)
{
Form form = sender as Form;
form.Visible = false;
form.Close();
}
}
- Add a Form1.cs with the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Debug.WriteLine("Form1_FormClosing");
}
}
- Start the Addin in Microsoft Word.
- Open a document that is marked as 'Read only', for example by checking the 'Read only' checkbox in the file attributes.
What goes wrong?
Word shows and hide a balloon under the Viewing button in the right top corner. It shows the Form1 and then it closes Form1 right away without any user interaction.
How should it work?
Form1 should stay modal and should not be closed by Word.
Workaround. We have managed to workaround this issue by calling the Activate() method of the Application, but we don't think that is a correct solution.
Globals.ThisAddIn.Application.Activate(); // Workaround: by reactivating the application the closing of the form
If we look at the callstack, then you can see that the showDialog is called and later in the callstack the dialog is closed.
We suspect that the closing of the balloon below also triggers a close of our custom form. These should not interfere with each other.
Can this bug be fixed by Microsoft and/or is there a good workaround available in the meantime?