Visual Studio 2017 - Message filter indicated that the application is busy

1

I'm porting over a small console application that deletes files on disk that are not in a Visual Studio project. This code worked in Visual Studio 2013, but I'm receiving the following error when I ran it in Visual Studio 2017:

System.Runtime.InteropServices.COMException: 'The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER))'

Current Code:

public static int DeleteFilesNotInProject(string solutionFileAndPath, string projectName, string extension)
    {
        var returnValue = 0;
        EnvDTE80.DTE2 dte;

        // Targets Visual Studio 2017
        dte = (EnvDTE80.DTE2)Activator.CreateInstance(Type.GetTypeFromProgID("VisualStudio.DTE.15.0", true), true);

        MessageFilter.Register();

        System.Threading.Thread.Sleep(2000);

        while (!dte.Solution.IsOpen)
        {
            // make sure it is ready to open
            System.Threading.Thread.Sleep(500);
            dte.Solution.Open(solutionFileAndPath);
        }

        dte.Solution.Open(solutionFileAndPath);

        System.Threading.Thread.Sleep(5000);

        foreach (Project project in dte.Solution.Projects)
        {
            if (project.UniqueName.EndsWith(projectName))
                foreach (string s in GetFilesNotInProject(project, extension))
                {
                    FileInfo fi = new FileInfo(s);
                    File.SetAttributes(s, FileAttributes.Normal);
                    File.Delete(s);
                    returnValue++;
                }
        }

        dte.Quit();

        MessageFilter.Revoke();

        return returnValue;
    }

The exception is thrown on the while (!dte.Solution.IsOpen) line. I tried commenting that out and then it is thrown on the foreach (Project project in dte.Solution.Projects) line instead.

Notes:

  • The code is based on this MSDN article. I'm looking to keep this in a Console Application.
  • I found PowerShell, and VS Addons/Extensions, but I'm interested in keeping this a C# class called withing a Console Application.
  • I tried using just the EnvDTE, instead of EnvDTE80 but received the same error.
c#
.net
visual-studio
visual-studio-2017
envdte
asked on Stack Overflow May 11, 2018 by Josh • edited May 11, 2018 by Nisse Engström

1 Answer

6

The implementation of the IOleMessageFilter registered using the CoRegisterMessageFilter function must be in a STA apartment thread.

From the CoRegisterMessageFilter function documentation:

Only one message filter can be registered for each thread. Threads in multithreaded apartments cannot have message filters.

Your question stated that you are porting over a small console application and indicates that you are using C#. I don't know exactly what porting implies, but if the original code was in VB.Net, VB.Net automatically marks Console applications with the STAThreadAttribute where-as C# does not and as such the thread is created in a MTA thread.

In C#, you apply the attribute to the entry method (Main) as shown below.

namespace ConsoleApp1
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
        }
    }
}
answered on Stack Overflow May 12, 2018 by TnTinMn

User contributions licensed under CC BY-SA 3.0