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 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)
{
}
}
}
User contributions licensed under CC BY-SA 3.0