Расширение Visual Studio: как получить «путь» к папке решения при выборе? - PullRequest
0 голосов
/ 09 февраля 2019

Предыдущий вопрос: Расширение Visual Studio: как отключить встроенную команду?

Я создаю расширение, которое правильно управляет модулями Git, и для этого у меня есть папка в решениипод названием SubModules.

Мне удалось добавить свое контекстное меню в файл решения и в файлы проекта, но я бы хотел отключить некоторые собственные команды при щелчке правой кнопкой мыши по моей папке SubModules (например, Удалить, Добавить).

Теперь я знаю, как отключить нужные собственные команды, но для этого мне нужно получить «путь» выбранной папки решений.

Я пытался реализовать IVsSelectionEvents, ноне повезло (o не равен нулю перед приведением):

public int OnSelectionChanged(IVsHierarchy pHierOld, uint itemidOld, IVsMultiItemSelect pMISOld, ISelectionContainer pSCOld, IVsHierarchy pHierNew, uint itemidNew, IVsMultiItemSelect pMISNew, ISelectionContainer pSCNew)
{
    var o = GetProjectItem(pHierNew, itemidNew);
    return VSConstants.S_OK;
}

private static ProjectItem GetProjectItem(IVsHierarchy hierarchy, uint itemId)
{
    object o;
    if (hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out o) == VSConstants.S_OK)
    {
        var t = o as SolutionFolder; // ==> null

        return o as ProjectItem; // ==> null
    }
    return null;
}

Используя код, который у меня был (из другого вопроса) (где я хочу найти «путь», но я мог бы справиться с вышеупомянутым"решение"), я пытался привести к SolutionFolder или FileProperties ... все еще не повезло;хотя MSDN сообщает, что возвращаемые объекты должны иметь тип FileProperties.Изучая QuickWatch для (Marshal.GetObjectForIUnknown(selectionContainerPtr) as ISelectionContainer), я могу перейти к просмотру частного свойства _nodes и там я могу увидеть свой узел SolutionFolder и перейти наверх, используя его свойство Parent, чтобы убедиться, что это папка, которую я хочу заблокировать командами.Вот фактический код:

private static void CommandEvents_BeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
{
    string name = GetCommandName(Guid, ID);

    if (name == "Project.AddNewSolutionFolder")
    {
        CancelDefault = true;
    }
    if (name == "Edit.Delete")
    {
        CancelDefault = true;

        IVsMultiItemSelect multiItemSelect = null;
        IntPtr hierarchyPtr = IntPtr.Zero;
        IntPtr selectionContainerPtr = IntPtr.Zero;
        uint itemid = 0;

        int hr = monitorSelection.GetCurrentSelection(out hierarchyPtr, out itemid, out multiItemSelect, out selectionContainerPtr);
        object[] selected = new object[2];
        (Marshal.GetObjectForIUnknown(selectionContainerPtr) as ISelectionContainer).GetObjects(2, 1, selected);


        var t = selected[0] as VSLangProj.FileProperties; // ==> null
        var t2 = selected[0] as SolutionFolder; // ==> null
        var b = 1;
    }

    if (name == "View.Branch")
    {
        //TODO: Could disable this command if not able to find the branch changing command (that would be cancelled and launch ours)
        menuBranchOpened = true;
    }

    if (menuBranchOpened)
    {
        var a = 1;
    }

}

Я был вдохновлен и попробовал (ни одна из них не работала, за исключением вышеперечисленного, кажется, действительно близко):

1 Ответ

0 голосов
/ 12 февраля 2019

Наконец, изучая (подробнее) веб-сайт другого человека, который ответил мне на мой предыдущий вопрос, я наконец нашел его.Поэтому я поделюсь методом, который я сделал, чтобы узнать, какой тип элементов выбран в обозревателе решений.

applicationObject = await ServiceProvider.GetGlobalServiceAsync(typeof(SDTE)) as DTE2; // Was initiate in a method

private enum SelectionTypes
{
    Other = 0,
    InSubModules = 1,
    IsAFolder = 2,
    IsAProject = 4,
    InAProject = 8
}

private static List<SelectionTypes> GetSelectionTypes()
{
    ThreadHelper.ThrowIfNotOnUIThread();
    var selectionTypes = new List<SelectionTypes>();

    EnvDTE.UIHierarchy solutionExplorer = applicationObject.ToolWindows.SolutionExplorer;
    object[] items = solutionExplorer.SelectedItems as object[];
    //{ Name = "WindowBase" FullName = "Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase"}
    if (items.Length > 0)
    {
        for (int i = 0; i < items.Length; i++)
        {
            var selectionType = SelectionTypes.Other;
            var selectedItem = items[0] as EnvDTE.UIHierarchyItem;
            var currentItem = selectedItem;
            var subModulesParentsCount = 0;
            var countingSubModulesParents = false;
            var nbParents = -1;

            if (currentItem.Object.GetType().FullName == "Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAProject") selectionType |= SelectionTypes.IsAProject;
            if (currentItem.Object.GetType().FullName == "Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAFolderItem") selectionType |= SelectionTypes.IsAFolder;

            while (currentItem != null)
            {
                nbParents++;
                if (countingSubModulesParents) subModulesParentsCount++;

                if (currentItem.Name == "SubModules")
                {
                    subModulesParentsCount = 0;
                    countingSubModulesParents = true;
                }

                if (currentItem.Object.GetType().FullName == "Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.Automation.OAProject") selectionType |= SelectionTypes.InAProject;

                currentItem = currentItem.Collection.Parent as EnvDTE.UIHierarchyItem;
            }

            if (selectionType == SelectionTypes.Other && nbParents != 0) selectionType |= SelectionTypes.IsAFolder;

            if (subModulesParentsCount == 1)
            {
                selectionType |= SelectionTypes.InSubModules;
            }

            selectionTypes.Add(selectionType);
        }
    }

    return selectionTypes;
}
...