Visual Studio 扩展:如何获取“路径"选择的解决方案文件夹? [英] Visual Studio Extension: How to get the "path" of a solution folder on selection?
问题描述
上一个问题: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);返回 VSConstants.S_OK;}私有静态 ProjectItem GetProjectItem(IVsHierarchy 层次结构,uint itemId){对象 o;if (hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out o) == VSConstants.S_OK){var t = o 作为解决方案文件夹;//==>空值将 o 作为 ProjectItem 返回;//==>空值}返回空;}
使用我拥有的代码(来自另一个问题)(我想在其中找到路径",但我可以使用上述解决方案"进行管理),我尝试将其转换为 SolutionFolder 或 FileProperties ...仍然没有运气;即使 MSDN 告诉返回的对象应该是 FileProperties 类型.在 (Marshal.GetObjectForIUnknown(selectionContainerPtr) as ISelectionContainer)
上使用 QuickWatch 进行探索,我可以进入查看私有属性 _nodes
,然后在那里我可以看到我的 SolutionFolder 节点并继续使用它的 Parent 属性来确保它是我想要阻止命令的文件夹.实际代码如下:
private static void CommandEvents_BeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault){字符串名称 = 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(outhierarchyPtr, out itemid, out multiItemSelect, out selectionContainerPtr);对象 [] 选择 = 新对象 [2];(Marshal.GetObjectForIUnknown(selectionContainerPtr) as ISelectionContainer).GetObjects(2, 1, selected);var t = selected[0] 作为 VSLangProj.FileProperties;//==>空值var t2 = selected[0] 作为解决方案文件夹;//==>空值无功b = 1;}if (name == "View.Branch"){//TODO:如果找不到分支更改命令,可以禁用此命令(这将被取消并启动我们的)menuBranchOpened = true;}如果(menuBranchOpened){变量 a = 1;}}
我受到启发并尝试过(除了上面那个似乎非常接近之外,没有任何效果):
最后,探索(更多)另一个回答我之前问题的人的网站,我终于找到了.所以我将分享一个我用来知道在解决方案资源管理器中选择什么类型的项目的方法.
applicationObject = await ServiceProvider.GetGlobalServiceAsync(typeof(SDTE)) as DTE2;//在一个方法中启动私有枚举 SelectionTypes{其他 = 0,子模块 = 1,IsAFolder = 2,IsAProject = 4,项目中 = 8}私有静态列表获取选择类型(){ThreadHelper.ThrowIfNotOnUIThread();var selectionTypes = new List();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;计数SubModulesParents = 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);}}返回选择类型;}
Previous question: Visual Studio Extension: How to disable native command?
I build an extension that manages correctly Git Modules and, to do so, I have a folder in the solution called SubModules.
I managed to add my context menu to the solution file and to the project files, but I would like to disable some native commands when right-clicking on my SubModules folder (i.e. Remove, Add).
I now know how to disable the native commands I want, but to do so, I need to get the "path" of the selected Solution Folder.
I tried to implement IVsSelectionEvents, but no luck (o is not null before casting):
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;
}
Using the code I had (from the other question) (where I want to find the "path", but I could have managed with the above "solution"), I tried to cast to SolutionFolder or to FileProperties... still no luck; even though MSDN tells the returned objects are supposed to be of type FileProperties. Exploring with QuickWatch on (Marshal.GetObjectForIUnknown(selectionContainerPtr) as ISelectionContainer)
, I can go in the see the private property _nodes
and there, I can see my SolutionFolder node and go up using its Parent property to ensure it is a folder I want to block commands. Here is the actual code:
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;
}
}
I was inspired by and tried (none worked except the above one seems to be really near) :
- Get Visual Studio Solution Files and Folders
- Visual Studio Extension: Get the path of the current selected file in the Solution Explorer
- How to get the details of the selected item in solution explorer using vs package
Finally, exploring (more) the website of the other person who answered me for my previous question, I finally found it. So I will share a method I made to know what type of items are selected in the Solution Explorer.
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;
}
这篇关于Visual Studio 扩展:如何获取“路径"选择的解决方案文件夹?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!