簡體   English   中英

Visual Studio 2017 - 消息過濾器指示應用程序正忙

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

我正在移植一個小型控制台應用程序,該應用程序刪除磁盤上不在 Visual Studio 項目中的文件。 此代碼在 Visual Studio 2013 中有效,但在 Visual Studio 2017 中運行時收到以下錯誤:

System.Runtime.InteropServices.COMException: '消息過濾器表明應用程序正忙。 (來自 HRESULT 的異常:0x8001010A (RPC_E_SERVERCALL_RETRYLATER))'

當前代碼:

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;
    }

while (!dte.Solution.IsOpen)行上拋出異常。 我嘗試將其注釋掉,然后將其拋出到foreach (Project project in dte.Solution.Projects)行上。

筆記:

  • 代碼基於這篇MSDN 文章 我希望將其保留在控制台應用程序中。
  • 我找到了 PowerShell 和 VS Addons/Extensions,但我有興趣將其保留為使用控制台應用程序調用的 C# 類。
  • 我嘗試只使用 EnvDTE,而不是 EnvDTE80,但收到了同樣的錯誤。

使用CoRegisterMessageFilter函數注冊的IOleMessageFilter的實現必須在STA單元線程中。

從CoRegisterMessageFilter函數文檔中:

每個線程只能注冊一個消息過濾器。 多線程單元中的線程不能具有消息過濾器。

您的問題表明您正在移植一個小型控制台應用程序,並表明您正在使用C#。 不確切知道移植的含義,但是如果原始代碼在VB.Net中,則VB.Net會自動使用STAThreadAttribute標記控制台應用程序,而C#則不會,因此該線程是在MTA線程中創建的。

在C#中,將屬性應用於輸入方法( Main ),如下所示。

namespace ConsoleApp1
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
        }
    }
}

所以我對這個問題有類似的問題。 我按照接受的答案中的指示添加了 STAThread 屬性,但除了獲得RPC_E_SERVERCALL_RETRYLATER異常之外,我還獲得了RPC_E_CALL_REJECTED異常。 經過一番谷歌搜索后,我發現了以下 MS 文檔:

https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ms228772(v=vs.100)?redirectedfrom=MSDN

來自 MS 的上述文檔指出,為了避免這些錯誤,我們可以實現一個 COM 消息過濾器 (IOleMessageFilter),它只是告訴 COM 接口在我們收到RPC_E_CALL_REJECTED消息時重試,並在我們收到RPC_E_SERVERCALL_RETRYLATER消息時等待。

希望這對迷路的人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM