Create VS extension with Analyzer and Options Page for Visual Studio 2022 - visual-studio-extensions

I am trying (and failing) to port a Visual Studio [extension][1] to the latest version of Visual Studio.
The extension provides a set of Roslyn analyzers and code fixes as well as an options page to configure some aspects of the analyzers' operation.
A reduction of the problem can be demonstrated with the following steps:
Follow instructions [here][2] to create an analyzer
Follow instructions [here][3] to create an options page
Now try to combine the two into a single VSIX.
I have tried starting from #1 and then adding relevant items from #2 and vice versa. To no avail.
Unfortunately the two samples produce different project types, and target different .NET frameworks which doesn't simplify things.
Depending on which sample I start with either the analyzers or the options page are not loaded.
Here is what the .vsixmanifest looks like (started by using the options page sample and then adding in the analyzer code):
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="MyToolsOptionsExtension.208a3dc2-4dd7-40db-bb6c-ab135b5ddaca" Version="1.0" Language="en-US" Publisher="ME" />
<DisplayName>MyToolsOptionsExtension</DisplayName>
<Description xml:space="preserve">Empty VSIX Project.</Description>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Community" Version="[17.0, 18.0)">
<ProductArchitecture>amd64</ProductArchitecture>
</InstallationTarget>
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" />
<Dependency Id="Microsoft.VisualStudio.MPF.16.0" DisplayName="Visual Studio MPF 16.0" d:Source="Installed" Version="[16.0,17.0)" />
</Dependencies>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[17.0,18.0)" DisplayName="Visual Studio core editor" />
<Prerequisite Id="Microsoft.VisualStudio.Component.Roslyn.LanguageServices" Version="[15.0,)" DisplayName="Roslyn Language Services" />
</Prerequisites>
<Assets>
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
<Asset Type="Microsoft.VisualStudio.Analyzer" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
</Assets>
</PackageManifest>
How can I debug why a specific asset defined in the .vsixmanifest file is not being loaded?
Would be great to see a sample where these are combined.
Peering into the compiled *.vsix (as zip file) it looks like an error in the auto-generation of the .pkgdef / catalog.json file, depending on what kind of project I start from. One or the other is missing from here despite having an identical vsixmanifest. For example catalog.json looks like this (note that the options page is missing):
"manifestVersion": "1.1",
"info": {
"id": "Analyzer1.2d1c1928-c190-4711-b986-1f7d0f3d8f5c,version=1.0",
"manifestType": "Extension"
},
"packages": [
{
"id": "Component.Analyzer1.2d1c1928-c190-4711-b986-1f7d0f3d8f5c",
"version": "1.0",
"type": "Component",
"extension": true,
"dependencies": {
"Analyzer1.2d1c1928-c190-4711-b986-1f7d0f3d8f5c": "1.0",
"Microsoft.VisualStudio.Component.CoreEditor": "15.0",
"Microsoft.VisualStudio.Component.Roslyn.LanguageServices": "15.0"
},
"localizedResources": [
{
"language": "en-US",
"title": "Analyzer1",
"description": "This is a sample diagnostic extension for the .NET Compiler Platform (\"Roslyn\")."
}
]
},
{
"id": "Analyzer1.2d1c1928-c190-4711-b986-1f7d0f3d8f5c",
"version": "1.0",
"type": "Vsix",
"payloads": [
{
"fileName": "Analyzer1.Vsix.vsix",
"size": 33906
}
],
"vsixId": "Analyzer1.2d1c1928-c190-4711-b986-1f7d0f3d8f5c",
"extensionDir": "[installdir]\\Common7\\IDE\\Extensions\\pv2xi53w.cfr",
"installSizes": {}
}
]
}```
[1]: https://marketplace.visualstudio.com/items?itemName=YoavFrandzel.CheckedExceptions
[2]: https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix
[3]: https://learn.microsoft.com/en-us/visualstudio/extensibility/creating-an-options-page?view=vs-2022

Related

Runing a functions project locally

I am truing to get a existing .Net functions app runing locally. It has been developed on Windows with Visual Studio, but I am on a Mac (M1 CPU) and using VS Code. I am pretty new to .Net I am struggeling to figure out what needs to be configured to get the project running.
I have added a launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to .NET Functions",
"type": "coreclr",
"request": "attach",
"processId": "${command:azureFunctions.pickProcess}"
}
]
}
and a local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
and there is a tasks.json already in the project:
{
"version": "2.0.0",
"tasks": [
{
"label": "clean (functions)",
"command": "dotnet",
"args": [
"clean",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"type": "process",
"problemMatcher": "$msCompile",
"options": {
"cwd": "${workspaceFolder}/Naboor.Statistics"
}
},
{
"label": "build (functions)",
"command": "dotnet",
"args": [
"build",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"type": "process",
"dependsOn": "clean (functions)",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": "$msCompile",
"options": {
"cwd": "${workspaceFolder}/Naboor.Statistics"
}
},
{
"label": "clean release (functions)",
"command": "dotnet",
"args": [
"clean",
"--configuration",
"Release",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"type": "process",
"problemMatcher": "$msCompile",
"options": {
"cwd": "${workspaceFolder}/Naboor.Statistics"
}
},
{
"label": "publish (functions)",
"command": "dotnet",
"args": [
"publish",
"--configuration",
"Release",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"type": "process",
"dependsOn": "clean release (functions)",
"problemMatcher": "$msCompile",
"options": {
"cwd": "${workspaceFolder}/Naboor.Statistics"
}
},
{
"type": "func",
"dependsOn": "build (functions)",
"options": {
"cwd": "${workspaceFolder}/Naboor.Statistics/bin/Debug/net6.0"
},
"command": "host start",
"isBackground": true,
"problemMatcher": "$func-dotnet-watch"
}
]
}
Should I be able to run this project from the commandline somehow? Do I need to point to a task in the tasks.json?
If I run it with F5 in VS Code, I get this error:
Executing task: func host start
Can't determine project language from files. Please use one of [--csharp, --javascript, --typescript, --java, --python, --powershell, --custom]
Can't determine project language from files. Please use one of [--csharp, --javascript, --typescript, --java, --python, --powershell, --custom]
Can't determine project language from files. Please use one of [--csharp, --javascript, --typescript, --java, --python, --powershell, --custom]
Azure Functions Core Tools
Core Tools Version: 4.0.4544 Commit hash: N/A (64-bit)
Function Runtime Version: 4.3.2.18186
Can't determine project language from files. Please use one of [--csharp, --javascript, --typescript, --java, --python, --powershell, --custom]
Can't determine project language from files. Please use one of [--csharp, --javascript, --typescript, --java, --python, --powershell, --custom]
[2022-05-25T12:24:12.674Z] Failed to initialize worker provider for: /opt/homebrew/Cellar/azure-functions-core-tools#4/4.0.4544/workers/python
[2022-05-25T12:24:12.682Z] Microsoft.Azure.WebJobs.Script: Architecture Arm64 is not supported for language python.
[2022-05-25T12:24:12.991Z] Failed to initialize worker provider for: /opt/homebrew/Cellar/azure-functions-core-tools#4/4.0.4544/workers/python
[2022-05-25T12:24:12.991Z] Microsoft.Azure.WebJobs.Script: Architecture Arm64 is not supported for language python.
[2022-05-25T12:24:13.118Z] A host error has occurred during startup operation 'a0f1f8a3-92f6-434a-9ab1-17055f0828f4'.
[2022-05-25T12:24:13.118Z] Microsoft.Azure.WebJobs.Script.WebHost: Secret initialization from Blob storage failed due to missing both an Azure Storage connection string and a SAS connection uri. For Blob Storage, please provide at least one of these. If you intend to use files for secrets, add an App Setting key 'AzureWebJobsSecretStorageType' with value 'Files'.
Value cannot be null. (Parameter 'provider')
The terminal process "/opt/homebrew/bin/zsh '-c', 'func host start'" terminated with exit code: 1.
I thought that was what the "FUNCTIONS_WORKER_RUNTIME": "dotnet" part of local.settings.json was for?
I am pretty new to this, can anybody guide me on the correct path?
Thank you
Søren
In order to configure VSCode launch tasks etc I would recommend installing the Azure Functions extension from the marketplace:
https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions
Once that is installed you can open the project and it will likely detect the functions project and ask if you want to initiliase for use with VSCode. If it does not then you can use the option from the command palette.
You may also be able to just run func init against the project to initiliase any files that may be missing.
Please ensure any files are tracked in git or backed up before making changes to the existing files
Having worked with Azure Functions on both Windows and Mac (non-M1) I would highly recommend using devcontainers for development. This means you don't have to have the SDK/Runtime/Functions Core Tools installed locally and means anyone using the project can just spin up the container and begin debugging without having to install a bunch of dependencies.
https://code.visualstudio.com/docs/remote/containers
We have tried the same in our local and able to run it successfully.
I believe that you are just missing the configuration in your local .
Here are the steps :-
Make sure the Azure function runtime , Dotnet sdk, storage emulator has been installed in your local . If not you can download from VS CODE extension called AZURITE instead of emulator as it has been deprecated.
In VS CODE install extensions Azure where all the tools will be available , c# (Any language that you want to prefer) & Azure function being installed.
.
If you want to create new project click f1> Select create new azure function . As you have existing file there is no need to point task.json file once the aforementioned has been done test your project by running :
. dotnet build once build succeed run ,
. func host start (If you have existing/new project don't run func init as it will create one more .csproj file and then it may occur to fail)
SNAPSHOTS FOR REFERENCE:-
STORAGE EMULATOR STARTED IN LOCAL:-
For more information please refer this MICROSOFT DOCUMENTATION| STEP BY STEP TUTORIAL TO CREATE AZURE FUNCTION IN VS CODE.
Alternatively, If you want to learn using Visual studio Create Azure function on Macos please refer this MICROSOFT DOCUMENTATION.

Adding custom jmx metrics to google cloud monitoring collectd configuration

I've added the JVM Monitoring plugin as described here
That's all working great and I can, but now I'd like to add more JMX metrics. e.g. MemoryPool specific counters
So I've added this config to /opt/stackdriver/collectd/etc/collectd.d/jvm-sun-hotspot.conf
<MBean "jvm_localhost_MemoryPool">
ObjectName "java.lang:type=MemoryPool,name=*"
InstanceFrom "name"
<Value>
Type "gauge"
InstancePrefix "memorypool-usage_used"
Table false
Attribute "Usage.used"
</Value>
</MBean>
and
Collect "jvm_localhost_MemoryPool"
in the Connection section
It seems to be valid collectd config but when it's getting sent to Stackdriver/Google Cloud Monitoring it is rejected.
012 {#012 "index": 261,#012 "valueErrors": [#012 {#012 "error": {#012 "code": 3,#012 "message": "Unsupported
collectd id: plugin: \"jvm\" type: \"gauge\" type_instance: \"memorypool-usagecommitted\""#012 }#012 }#012 ]#012 },#012 {#012
"index": 262,#012 "valueErrors": [#012 {#012 "error": {#012 "code": 3,#012 "message": "Unsupported collectd id: plug
in: \"jvm\" type: \"gauge\" type_instance: \"memorypool-usageinit\""#012 }#012 }#012 ]#012 },#012 {#012 "index": 263,#012
"valueErrors": [#012 {#012 "error": {#012 "code": 3,#012 "message": "Unsupported collectd id: plugin: \"jvm\" type: \"gau
ge\" type_instance: \"memorypool-usagemax\""#012 }#012 }#012 ]#012 },#012 {#012 "index": 264,#012 "valueErrors": [#012
{#012 "error": {#012 "code": 3,#012 "message": "Unsupported
Now from what I understand it needs to be added as a custom metric, but this document suggests it would be auto created.
And indeed when I look at the list of builtin jvm metrics I can't see how they map onto the existing ones in the collectd configuration.
e.g. how is os-open_fd_count mapped to os/open_files ?
It would be helpful to see the actual api request being sent by Google's custom collectd implementation but I can't see a way of increasing logging.
I can see from this post that it's probably custom metrics where I want to be looking but how do I do that in the collectd configuration?
I've tried
InstancePrefix "custom.googleapis.com/memorypool-usage"
but still no joy.
Has anyone done this before or can offer any suggestions on what I'm doing wrong?
To get this logging I needed to add stackdriver_metric_type metadata.
The complete chain is now
<Chain "GenericJMX_jvm">
<Rule "rewrite_custom_jmx">
<Match regex>
Plugin "^GenericJMX$"
PluginInstance "^jvm.*$"
TypeInstance "^memorypool-usage_used$"
</Match>
<Target "set">
MetaData "stackdriver_metric_type" "custom.googleapis.com/jvm/memorypool/usage_used"
MetaData "label:pool" "%{plugin_instance}"
</Target>
<Target "replace">
MetaData "label:pool" "jvm" ""
</Target>
</Rule>
<Rule "rewrite_genericjmx_to_jvm">
<Match regex>
Plugin "^GenericJMX$"
PluginInstance "^jvm.*$"
</Match>
<Target "replace">
PluginInstance "jvm" ""
</Target>
<Target "set">
Plugin "jvm"
</Target>
Target "return"
</Rule>
</Chain>
The plugin instance is the pool name (e.g. G1 Eden Space) which is why I copied it into the 'pool' label.
This did auto-create the metric in Stackdriver but I also used the following body to the projects.metricDescriptors.create method to add description and units.
{
"name": "projects/yourprojecthere/metricDescriptors/custom.googleapis.com/jvm/memorypool/usage_used",
"labels": [
{
"key": "pool",
"description": "Name of the JVM memory pool."
}
],
"metricKind": "GAUGE",
"valueType": "DOUBLE",
"unit": "By",
"description": "Current size in bytes of the memory pool.",
"type": "custom.googleapis.com/jvm/memorypool/usage_used",
"monitoredResourceTypes": [
"gce_instance"
]
}
The resulting graph in metric explorer looks like this
The troubleshooting documents [1] could be helpful to determine what points need to be transformed, as well as to ensure your transformations behave as expected.
[1] https://cloud.google.com/monitoring/agent/custom-metrics-agent#troubleshooting

How do I change the name of a dotnet new template when creating new projects?

I've created a dotnet template for use with dotnet new. When creating new projects from this template, it works fine however the assembly and namespace name is still "Template", rather than the new project.
I've tried creating a new project and manually setting the name with the --name flag and --output flag, but to no avail.
I suspect there's a variable I can use somewhere, perhaps in the template.json file?
Thanks,
You have to set template then use option params like -n param and give name.
For example,
dotnet new web -n myBestName
you can see more about cli
source click here
You need to set sourceName in your template.json file.
You can refer to this page to find the purpose of each field.
"sourceName": {
"description": "The name in the source tree to replace with the name the user specifies",
"type": "string"
},
http://json.schemastore.org/template
A basic example of template.json file would look like this. Notice the sourceName
{
"$schema": "http://json.schemastore.org/template",
"author": "Me",
"classifications": [ "web api", "asp.net core", "C#" ],
"identity": "WebApi.Template",
"name": "WebApi.Template",
"shortName": "WebApiTemplate",
"tags": {
"language": "C#",
"type": "project"
},
"sourceName": "WebApi.Template",
"preferNameDirectory" : true
}
If you use template.json similar to above, you can give your component name in cli command either with dotnet new YourTemplateName -n YourComponentName or running just dotnet new YourTemplateName inside the folder named with your component name.

Using Shared Libraries with .NET Core

I wrote my open source library, LINQ to Twitter, with shared libraries to minimize deployment artifacts and handle platform specific features. I want to support .NET Core and am thinking that the fastest approach would be to reference the shared libraries. The Add References dialog didn't show the shared libraries, so I tried project.json:
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"LinqToTwitter.Shared": "*",
"LinqToTwitter.Shared.net": "*"
},
"frameworks": {
"netstandard1.6": {
"imports": "dnxcore50"
}
}
}
I tried a few combinations of versions, but didn't get anywhere. The error messages contain something like this:
The dependency LinqToTwitter.Shared >= * could not be resolved.
Next, I opened the *.xproj and pasted the following Imports into the Project section:
<Import Project="..\LinqToTwitter.Shared\LinqToTwitter.Shared.projitems"
Label="Shared" />
<Import
Project="..\LinqToTwitter.Shared.net\LinqToTwitter.Shared.net.projitems"
Label="Shared" />
This doesn't show references in VS, nothing in metadata, and (as it would follow) can't reference any shared library types from a console app that references the .NET core app.
if library is in the same solution you can reference it using target:project something like
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"LinqToTwitter.Shared": {"target": "project"},
"LinqToTwitter.Shared.net": {"target": "project"}
},
"frameworks": {
"netstandard1.6": {
"imports": "dnxcore50"
}
}
}
Good news - Visual Studio 2017 now allows .NET Core library projects to reference Shared projects.

Mocking framework for ASP.net 5.0 vnext class library project

I have created a ASP.net vnext class library project in Visual Studio 2015. Now I want to test my project. So, I want to use mocking stuffs in my test project.
Here is my project.json file
{
"version": "1.0.0-*",
"dependencies": {
"xunit": "2.0.0-rc3-build2880",
"xunit.runner.aspnet": "2.0.0-rc3-build52",
"My project name with version",
"Moq": "4.2.1502.911"
},
"commands": { "test": "xunit.runner.aspnet" },
"frameworks": {
"aspnet50": {
"dependencies": {
}
}
}
}
But I am getting error :Dependency Moq with the Version 4.2.1502.911 could not be resolved.
I also tried different version of Moq, but results the same: dependency error.
Without Mock I can't move further in testing.
Any help?
based on comment, the error is incorrect package manager settings :
the correct feeds to use are : nuget.org/api/v2 and myget.org/F/aspnetrelease for the asp ones

Resources