[BUG] IsKindAsync not working [for me?]
IsKindAsync does not return true, and my project menu item remains hidden. What am I doing wrong?
(Project is a .NET Core 3.1 Console app, C#, .csproj)
private async void OnProjectMenuBeforeQueryStatus(object sender, EventArgs e)
{
var menuCommand = sender as MenuCommand;
if (menuCommand == null)
{
return;
}
var project = await VS.Solutions.GetActiveProjectAsync();
if (project == null)
{
return;
}
menuCommand.Visible =
project.FullPath.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase);
//TODO Report bug
//(await project.IsKindAsync(ProjectTypes.CSHARP)) ||
//(await project.IsKindAsync(ProjectTypes.DOTNET_CORE));
return;
}
Related issue https://github.com/ErikEJ/EFCorePowerTools/issues/1046
Interesting. Looks like SDK-style projects are not IVsAggregatableProject.
This line is false for SDK-style projects, but true for other projects. https://github.com/VsixCommunity/Community.VisualStudio.Toolkit/blob/5c266503acbf4fc532a3d4b5b167745d33d3891e/src/Community.VisualStudio.Toolkit.Shared/ExtensionMethods/IVsHierarchyExtensions.cs#L85
@reduckted any idea on how to fix?
Unfortunately, no. I had a search across GitHub for places that were using IVsAggregatableProject and I didn't see anywhere that was using an alternative technique when the hierarchy doesn't implement that interface.
🤔 I'm just thinking out loud here. I wonder if using project capabilities are a better choice in this situation. For a .NET Framework C# project, the capabilities are:
AppServicePublish
CSharp
FolderPublish
Managed
Publish
SharedProjectReferences
WindowsForms
And for a .NET Core C# application they are:
.NET
AllTargetOutputGroups
AppDesigner
AssemblyReferences
CPS
CSharp
ClassDesigner
...plus another 36 capabilities...
VisualStudioWellKnownOutputGroups
WinRTReferences
From that, you could detect a .NET Core C# project by looking for the CSharp and CPS capabilities. A .NET Framework C# project would have the CSharp capability but not the CPS capability.
I wonder if each project type listed in ProjectTypes.cs has a corresponding capability...
That would work fine, can I do This today With the toolkit?
Not directly with the toolkit, but it's not a lot of code:
Project project = await VS.Solutions.GetActiveProjectAsync();
project.GetItemInfo(out IVsHierarchy hierarchy, out _, out _);
bool isCSharp = hierarchy.IsCapabilityMatch("CSharp");
bool isCSharpAndNetCore = hierarchy.IsCapabilityMatch("CSharp & CPS");
bool isCSharpAndNetFx = hierarchy.IsCapabilityMatch("CSharp & !CPS");
Here's some more information about the capability expressions: IsCapabilityMatch(IVsHierarchy, String)
This is what I used to get all of the capabilities:
HierarchyUtilities.TryGetHierarchyProperty<string>(h, itemId, (int)__VSHPROPID5.VSHPROPID_ProjectCapabilities, out string value);
string[] capabilities = (value ?? "").Split(' ');
Cool, thanks!
Same question for ASP.Net core project types. is there any capability or something which gives info about which sdk is in use? I found a workaround here. it uses Microsoft.Build to analyse sdk types. this is working fine but not sure if it's a good idea to have dependencies to Microsoft.Build...
@jaybee82 you should be able to look at the capabilities as mentioned above.
That us what works fine for me, and I would imagine there is a Web related capability also.
Ok, thank you. i will check. for some reason i missed comment from @reduckted how to list all capabilities.
The CI build has a way to ask for Project.IsCapabilityMatch(string). It would be cool if we can make a list of known capability names so we can provide IntelliSense for it. Perhaps an overload that takes an enum
Here's a list of some of the known capabilities: https://github.com/microsoft/VSProjectSystem/blob/master/doc/overview/project_capabilities.md
It's not a complete list though, because it's missing these ASP.NET Core capabilities: https://github.com/dotnet/sdk/blob/a30e465a2e2ea4e2550f319a2dc088daaafe5649/src/WebSdk/ProjectSystem/Targets/Microsoft.NET.Sdk.Web.ProjectSystem.targets#L28-L31