C# 从VisualStudio扩展添加解决方案项

C# 从VisualStudio扩展添加解决方案项,c#,visual-studio-extensions,vsix,C#,Visual Studio Extensions,Vsix,我正在测试VisualStudio扩展,它向解决方案中添加了新项。我通过反复试验找到了解决问题的方法,但我对这个解决方案的复杂性并不满意,我还有一些有待解决的问题。。代码如下: using EnvDTE; using EnvDTE80; //.. namespace MyFirstExtension { internal sealed class AddFileToSolution { public const int CommandId = PackageId

我正在测试VisualStudio扩展,它向解决方案中添加了新项。我通过反复试验找到了解决问题的方法,但我对这个解决方案的复杂性并不满意,我还有一些有待解决的问题。。代码如下:

using EnvDTE;
using EnvDTE80;
//..

namespace MyFirstExtension
{
    internal sealed class AddFileToSolution
    {
        public const int CommandId = PackageIds.CmdCreateVaultHelperConfig;
        public static readonly Guid CommandSet = new Guid(PackageGuids.guidVaultHelperVsExtensionPackageCmdSetString);
        private readonly AsyncPackage package;

        private AddFileToSolution(AsyncPackage package, OleMenuCommandService commandService)
        {
            this.package = package ?? throw new ArgumentNullException(nameof(package));
            commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

            var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem = new MenuCommand(this.Execute, menuCommandID);
            commandService.AddCommand(menuItem);
        }

        public static AddFileToSolution Instance { get; private set; }

        private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider { get { return this.package; } }

        public static async Task InitializeAsync(AsyncPackage package)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

            OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
            Instance = new AddFileToSolution(package, commandService);
        }

        private async void Execute(object sender, EventArgs e)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            string fileFullPath = @"C:\Users\myusr\source\repos\VsExtensionTesting2\0.txt";
            
            var dte = await package.GetServiceAsync(typeof(DTE));
            var dte2 = dte as DTE2;

            var solution2 = (Solution2)dte2.Solution;
            
            // following line throws Exception!
            //solution2.AddFromFile(fileFullPath);

            bool isSolutionItemsFolderExists = IsSolutionItemsFolderExists(solution2);
            if (!isSolutionItemsFolderExists)
            {
                solution2.AddSolutionFolder("Solution Items");
            }

            AddToSolutionItems(solution2, fileFullPath);
        }

        public bool IsSolutionItemsFolderExists(Solution2 solution2)
        {
            foreach (var solutionItemObj in solution2)
            {
                var solutionItem = solutionItemObj as Project;

                string name = solutionItem.Name;
                if (name == "Solution Items")
                {
                    return true;
                }
            }

            return false;
        }

        public void AddToSolutionItems(Solution2 solution2, string fileFullPath)
        {
            foreach (var solutionItemObj in solution2)
            {
                var solutionItem = solutionItemObj as Project;

                string name = solutionItem.Name;
                if (name == "Solution Items")
                {
                    solutionItem.ProjectItems.AddFromFile(fileFullPath);
                }
            }
        }
    }
}
这里我使用的是
VisualStudio2019
VSIX项目模板。默认情况下,它使用
AsyncPackage
。我试图完成的是在
solution
级别执行命令
Project.AddExistingItem

问题是:

  • 在我的解决方案中-为什么调用命令
    solution2.AddFromFile(fileFullPath)直接引发异常
  • System.Runtime.InteropServices.COMException:'找不到指定的模板。请检查完整路径是否正确。”

    文件100%存在于目录中。。理想情况下,我希望避免自己创建
    解决方案项
    文件夹,让API来处理

  • 但是,在迭代解决方案项/项目时,我将这些项强制转换为键入
    Project
    ,在调试期间,我可以看到该项也由类型
    System.\uu ComObject
    Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAProject
    表示,但是无法将该项强制转换为这两种类型中的任何一种。。其他两种类型(或三种类型之间的相关性)是什么?我如何确切地知道应该将解决方案项转换到哪种类型

  • 查找VS执行的命令的用例是什么?我已经下载了commandexplorer并捕获了
    项目.AddExistingItem
    命令,但是我实际上如何使用这些知识从代码执行命令呢?以下是该命令的外观:


  • 我很高兴听到一些关于我上面提到的问题的解释。。到目前为止,我对VS扩展大楼的经验是——它需要大量的谷歌搜索和反复试验。。(与实际知道该做什么相反:)

    我无法获得有关
    PackageIds
    PackageIds
    的信息,你能提供它们并帮助我重现问题吗?@PerryQian MSFT CommandId是
    0x0101
    CommandSet
    guid值是
    “ed464f41-9d8c-4e2d-a43a-45904953bcd7”
    ,如果有关系的话。。您将找不到
    PackageIds
    类,因为它是由名为
    VsctGenerator
    的自定义工具自动生成的。这是2019年《扩展性要领》(Extensibility Essentials 2019)的一部分,我将对其进行测试。