Visual Studio 扩展:如何在选择时获取解决方案文件夹的 "path"?
Visual Studio Extension: How to get the "path" of a solution folder on selection?
上一题:
我构建了一个可以正确管理 Git 模块的扩展,为此,我在解决方案中有一个名为 SubModules 的文件夹。
我设法将我的上下文菜单添加到解决方案文件和项目文件中,但我想在右键单击我的 SubModules 文件夹(即删除、添加)时禁用一些本机命令。
我现在知道如何禁用我想要的本机命令,但要这样做,我需要获取所选解决方案文件夹的 "path"。
我尝试实现 IVsSelectionEvents,但没有成功(o 在转换前不为 null):
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;
}
使用我的代码(来自另一个问题)(我想在其中找到 "path",但我可以用上面的 "solution" 进行管理),我尝试转换为 SolutionFolder或 FileProperties... 仍然没有运气;尽管 MSDN 告诉返回的对象应该是 FileProperties 类型。在 (Marshal.GetObjectForIUnknown(selectionContainerPtr) as ISelectionContainer)
上使用 QuickWatch 进行探索,我可以查看私有 属性 _nodes
,在那里,我可以看到我的 SolutionFolder 节点并使用其父节点 属性 确保这是一个我想阻止命令的文件夹。这是实际的代码:
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;
}
}
我受到启发并尝试过(none 工作除了上面那个似乎真的很接近):
- Get Visual Studio Solution Files and Folders
- How to get the details of the selected item in solution explorer using vs package
最后,浏览(更多)回答我上一个问题的另一个人的网站,我终于找到了。因此,我将分享一个我用来了解在解决方案资源管理器中选择了哪些类型的项目的方法。
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;
}
上一题:
我构建了一个可以正确管理 Git 模块的扩展,为此,我在解决方案中有一个名为 SubModules 的文件夹。
我设法将我的上下文菜单添加到解决方案文件和项目文件中,但我想在右键单击我的 SubModules 文件夹(即删除、添加)时禁用一些本机命令。
我现在知道如何禁用我想要的本机命令,但要这样做,我需要获取所选解决方案文件夹的 "path"。
我尝试实现 IVsSelectionEvents,但没有成功(o 在转换前不为 null):
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;
}
使用我的代码(来自另一个问题)(我想在其中找到 "path",但我可以用上面的 "solution" 进行管理),我尝试转换为 SolutionFolder或 FileProperties... 仍然没有运气;尽管 MSDN 告诉返回的对象应该是 FileProperties 类型。在 (Marshal.GetObjectForIUnknown(selectionContainerPtr) as ISelectionContainer)
上使用 QuickWatch 进行探索,我可以查看私有 属性 _nodes
,在那里,我可以看到我的 SolutionFolder 节点并使用其父节点 属性 确保这是一个我想阻止命令的文件夹。这是实际的代码:
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;
}
}
我受到启发并尝试过(none 工作除了上面那个似乎真的很接近):
- Get Visual Studio Solution Files and Folders
- How to get the details of the selected item in solution explorer using vs package
最后,浏览(更多)回答我上一个问题的另一个人的网站,我终于找到了。因此,我将分享一个我用来了解在解决方案资源管理器中选择了哪些类型的项目的方法。
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;
}