I'd like to create a Visual Studio extension to allow the user to create a json file and automatically apply a custom JSON schema to it. I followed this article and so far, I succeeded in allowing the user to create the JSON file, but I have no idea how to automatically bind the custom schema to it.
I'd like this schema to be in the extension solution, this way, when I update the extension, the schema gets updated. As I'm using SideWaffle, I noticed that there is this "JSON Schema Selector Extension" item template but it does not work. It requires "Microsoft.Json.Core.Schema" that is nowhere to be found (not even in the Microsoft.JSON Nuget package...).
Late to this question, but the solution involves referencing a non-SDK VS assembly as of VS2019 (and everything prior). To prove it is non-SDK, it even changed identity in VS2019, it is now Microsoft.WebTools.Languages.Json as of VS2019 (whereas it was indeed Microsoft.Json.Core for older versions), and of course, it may change again in the future.
Knowing this, if you search online opensource repos, you will find some ideas for how to achieve the reference. Some people bundle a copy of the DLL in their repo (which is probably against some licensing terms). Personally, I did not go that route and I instead went for an overcomplicated path relative to $(MSBuildToolsPath):
<Reference Include="Microsoft.WebTools.Languages.Json">
<HintPath>$(MSBuildToolsPath)\..\..\..\Common7\IDE\Extensions\Microsoft\Web Tools\Languages\Microsoft.WebTools.Languages.Json.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>false</Private>
</Reference>
Just looking at this, it is obvious that this approach is brittle, and the path may move in the future, but it avoids bootstrapping the dll.
Anyway, whichever way you choose to reference the assembly, as for everything else that is meant to come from VS itself, make sure it is Private=false, as you do not want your final VSIX bundle to include it.
Then it is a simple matter of implementing IJsonSchemaSelector:
[Export(typeof(IJsonSchemaSelector))]
public class LaunchConfigJsonSchemaProvider : IJsonSchemaSelector
{
private static readonly string Schema = #"<somehow resolve your extension install path and find your schema json>";
public event EventHandler AvailableSchemasChanged { add { } remove { } }
public Task<IEnumerable<string>> GetAvailableSchemasAsync()
{
return Task.FromResult((IEnumerable<string>)new[] { Schema });
}
public string GetSchemaFor(string fileLocation)
{
string ext = Path.GetExtension(fileLocation);
if (!".greatjson".Equals(ext, StringComparison.OrdinalIgnoreCase))
return null;
return Schema;
}
}
Related
I am trying to add NuGet packages automatically when adding a custom item template in Visual Studio. The packages need to be referenced from nuget.org, deploying them locally in the ItemTemplate-Zipfiles is unfortunately no option.
What I have tried so far:
1.) Altering the packages.config programatically. As this requires the project to be reloaded and manual intervention to install the added packages, this is not really feasible
2.) Using NuGet.VisualStudio.Interop in the template wizard as well as adding it to the vstemplate file requires the NuGet packages to be stored locally. Since I need to them to be installed from nuget.org, this is no option either.
3.) Using the NuGet-API doesn't seem to work either, since it does not take the "project" parameter passed to it from envdte or vslangproj.
Any ideas would be very welcome.
Finally resolved it with this code:
List<string> packagesToInstall = new List<string>();
packagesToInstall.Add("SomeNuGetPackageIdentifier");
var componentModel = (IComponentModel)Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider.GetService(typeof(SComponentModel));
IVsPackageInstaller2 installer = componentModel.GetService<IVsPackageInstaller2>();
//Loop through the list of Strings and install the Packages.
foreach (string package in packagesToInstall)
{
try
{
installer.InstallLatestPackage(null, vsProj.Project, package, false, false);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
continue;
}
}
I've got a Xamarin.Forms app. at one time, I had this working, but alas, something has happened and now it no longer works. In my Android project, I have a dependency service as shown below. I am just trying to play a sound on the local system in the background. Now, out of the blue, I am getting an error on compile saying that 'Resource' does not contain a definition for 'Raw'. I have no idea where this error came from or how to fix it. There is a directory in Resource folder called raw. In it, there is a file named flushing.mp3. the VS intellisense does indicate the file is there. Any ideas are appreciated. TIA
Here is my code for my dependency service:
[assembly: Dependency(typeof(Audio))]
namespace PooperAppMobile.Droid.DependencyServices
{
public class Audio : IAudio
{
private MediaPlayer _mediaPlayer;
public bool PlayFlush()
{
_mediaPlayer = MediaPlayer.Create(global::Android.App.Application.Context, Resource.Raw.flushing);
_mediaPlayer.Start();
return true;
}
}
}
Well to be quite honest this error was giving me quite a pain when I saw this solution on a GITHUB discussion now all you have to do is add this line in your project file i.e. the .csproj, in your debug property group something like this :
<PropertyGroup.......
<AndroidUseManagedDesignTimeResourceGenerator>False</AndroidUseManagedDesignTimeResourceGenerator>
....
</PropertyGroup>
And It will start working as expected,
Good luck!
In case of queries do revert.
The question seems to be stupid since there are many explanations in internet, that describe how to add a new method that can be called by users of the resulting OCX later. Unfortunately it does not work for me.
I have a MFC-based ActiveX-control project that was created with Visual Studio 6 and was imported to VS2010. There I have NO class view where I could use the Wizard with to add a method (the class view tab pane is there but it is empty). The existing code also does not provide any callable methods until now so that I simply could copy them.
So: how can I enable/invoke the class view generation in VS2010 to use the Wizard?
And as soon as it works: What type should such a method be to be externally visible? From what I learned the Wizard asks for some type...
To add a method to your ActiveX control you have to follow the folliwng steps:
1. Declare the function in the header file.
e.g.
public:
int Connect(int timeout);
2. Add the definition in the CPP file.
int CSLWebLinkCtrl::Connect(int timeout)
// Your logic here.
return 0;
}
3. Expose your methods in the .idl file
[id(4), helpstring("method Connect")] int Connect(int timeout);
Hope it will help you. :)
Maybe the SDF file is corrupt?
If you right-click the Class View dialog bar, you should see a context menu option for Class Wizard. From there, you should be able to work with your project's classes.
I have the following file: Foo.cs with a Foo class inside of it. I can't seem to find the right way to keep my resource files (resx) organized behind their respective files.
If I create a Foo.resx the resource file gets folded away nice and tidy behind the Foo.cs class. This, however, causes issues because the standard custom-tool that generates the code attempts to create another Foo class (Look at the Foo.Designer.cs: internal class Foo { ... }). If my Foo.cs file does not already contain a Foo class, this works fine (no naming collision).
To fix the naming collision I attempted to give it a custom namespace MyProj.Resources and use an alias to identify it: using R = MyProj.Resources.Foo; This still causes issues because the auto-generator has an issue creating a ResourceManager properly.
If I, instead, name it something along the lines of FooResx.resx it does not automatically get folded behind the Foo.cs file. Instead, it resides in the solution explorer right below it. Going into the MSBuild (.csproj) file and adding a <DependentUpon> tag, then Visual Studio neatly tucks away my FooResx.resx file. However, I can't actually use any of the resources from that file because the auto-generated code has an issue creating a ResourceManager properly.
Basically, is there any way to have the Resource files (resx) fold behind a cs file and still work properly using the standard Custom Tool (ResXFileCodeGenerator)?
I do realize that I can always place all my resources into a file within the properties folder: resources.resx. I'm trying to organize them better than that though.
Update:
I decided to manually edit the auto-generated code and make it partial. This allowed the code to compile, but I still ran into the same issue (Issue #2). It seems that if a resource file is folded behind (manually or automatically) another code file then the ResourceManager has trouble finding the *.resource file. This might be an issue I'll have to raise with Microsoft Connect about the ResXFileCodeGenerator tool. It needs to be able to locate the proper *.resource file when folded behind other files.
The solution could be to make your classes and your generated code partial classes - if you look at a .Designer.cs (from a System.Windows.Forms.Form for example) you will discover that it declares something like partial class Foo.
Foo.cs
public partial class Foo
{
}
Foo.Designer.cs
partial class Foo
{
}
Edit
It turns out that StronglyTypedResourceBuilder or PublicResXFileCodeGenerator insists on generating classes with either internal or public access modifier (it can be set in the .resx).
Setting ResXFileCodeGenerator as the CustomTool in the properties of your .resx still doesn't give you the behaviour you'd see in a generated .Desinger.cs of a Form.
First, I know Silverlight project can't reference to non-Silverlight based project like Windows class library or Asp.net MVC project. But I need to create my projects which can support both Silverlight-based project & Asp.net MVC project.
So, I created Silverlight-based project for my sharing source code. It works fine on VS.net 2008 & .Net 3.5 SP1. However, I found some error when I try to use some method of Silverlight-based project from .Net-based project like the following code.
Silverlight-based Method
public static void InitializeInstance(object obj)
{
// Initialize Field Value
foreach (FieldInfo fi in obj.GetType().GetFields())
{
foreach (Attribute attr in fi.GetCustomAttributes(true))
{
if (attr is DefaultValueAttribute)
{
DefaultValueAttribute dv = (DefaultValueAttribute)attr;
fi.SetValue(obj, dv.Value);
}
}
}
// Initialize Property Value
foreach (PropertyInfo pi in obj.GetType().GetProperties())
{
foreach (Attribute attr in pi.GetCustomAttributes(true))
{
if (attr is DefaultValueAttribute)
{
DefaultValueAttribute dv = (DefaultValueAttribute)attr;
if (pi.CanWrite)
{
pi.SetValue(obj, dv.Value, null);
}
}
}
}
}
.Net-based Method
private void Form1_Load(object sender, EventArgs e)
{
InitializeInstance(this);
}
Error Detail
System.IO.FileNotFoundException:
Could not load file or assembly
'System, Version=2.0.5.0,
Culture=neutral,
PublicKeyToken=7cec85d7bea7798e' or
one of its dependencies. The system
cannot find the file specified. File
name: 'System, Version=2.0.5.0,
Culture=neutral,
PublicKeyToken=7cec85d7bea7798e' at
InitializeInstance(Object obj)
Finally, I try to solve this problem by copying system.dll of Silverlight to output directory and reference it. It still shows same error. So, I think this error may be limitation of both .Net & Silverlight platform. Do you have any idea for avoid this issue?
PS. I know I can use this technique for a few sharing code. But it’s impossible to do this for my projects. Because it’s very complicate & very complex more than directly create Silverlight-based or .Net-based class library.
Thanks,
The trouble here is that those types share an assembly with a different strong name: System.Windows in Silverlight, PresentationFramework or PresentationCore on the desktop CLR.
So at runtime, the intended type cannot be loaded, and there are no type forwarders for the Silverlight-to-desktop types.
My recommended solution
Consider using file links, instead of actually trying to reference the same built binary.
This way, you can have a source structure for your project that may look like this:
MyApp\
Silverlight\
Page.xaml
Page.xaml.cs
(link) ..\AspMvc\MySharedDataFile.cs
AspMvc\
MySharedDataFile.cs
MyApp.cs
This way, the source will be re-compiled with both projects. We use this on the Silverlight Toolkit to build many controls, including the charting and data visualization controls, for both WPF and Silverlight. This is by rebuilding for each platform, instead of referencing the binaries from both.
To insert a link in Visual Studio, just right-click on your project or one of its folder, Add Existing Item, then find it in the explorer open file dialog. however, instead of just clicking the button, click on the little down arrow drop-down on the Add file button, and select the "Add as link" option.
Then, it simply builds that file from another location, but it is not a copy, so you can maintain it in one place and use in both.
A crazy solution
You can use .NET reflection from your desktop app that is of a much higher trust to actually create a new app domain, hook up to the assembly resolution event, and see what that does. You may be able to instead return the type from the desktop CLR, or just no-op these warnings.
No clue if it works.