Thursday, November 19, 2020

A festive introduction to Visual Studio Extensions

Visual Studio is highly extensible. This article will show you two simple ways to extend it by adding additional content to the editor. What you add is up to you. It could be something practical, or it could be something fun, like this:

Screenshot of Visual Studio editor with holly in the corners, and images of Santa, Christmas trees, and snowflakes among the text

While there are many festive images included in the above screenshot, they are added in two ways.

The holly and mistletoe are Viewport Adornments. The smaller images among the text are Intra-text Adornments.

This post has three parts.

  1. Instructions on how to create an extension that adds these festive adornments to the editor.
  2. Examples of how that knowledge can be used to create more practical extensions.
  3. A video showing how to modify or extend the festive editor code.

Creating a festive editor extension

The code for this extension can be found at https://github.com/mrlacey/FestiveEditor.

If you don't want the code but simply want to install it, you can download it from the marketplace.

Creating a project

To create an extension for Visual Studio, you must have the 'Visual Studio extension development' workload installed. This option is available when installing or modifying an installation of Visual Studio.

The Visual Studio Installer showing the extension development workload option

We'll start by creating an Empty VSIX Project within Visual Studio.

Empty VSIX Project option in the Create a new project dialog
Let's call this project FestiveEditor.

Adding a viewport adornment

The first things to add to the extension are the holly and mistletoe images.

I'm using images from SweetClipArt.com, but you could use any images you want.

mistletoe with red ribbon Holly with berries

For simplicity, I've created versions of the holly image rotated for each corner it will be displayed in. 
The images are in a folder called Images, and I've set the Include in VSIX property to True so that they'll be distributed with the extension.

partial screenshot showing images in solution explorer and the properties window

Firstly, we'll create an adornment that will display the mistletoe. We do this by adding an item to the project of the type Editor Viewport Adornment. Let's call it MistletoeAdornment.cs.

Add New Item dialog showing Editor Viewport Adornment option

This adds two files and several references to the project.

Solution Explorer showing new files and references

MistletoeAdornmentTextViewCreationListener.cs is responsible for the creation of the image (adornment) that we add to the editor. Because this class will create all of the adornments that we add, let's give it the more generic name of FestiveEditorTextViewCreationListener.

This file does three things.

  1. It determines which editors it applies to.
  2. It defines the visual layer to which the images will be added.
  3. It creates a class that displays the image.

Determining which editors the adornment applies to.

The class implements and exports the interface IWpfTextViewCreationListener. The ExportAttribute tells Visual Studio, via MEF (the Managed Extensibility Framework) that this class wants to listen to TextView creation events. By specifying the ContentType as "text" and the TextViewRole as PredefinedTextViewRoles.Document Visual Studio knows to add this to all editors that allow the editing of text documents.

Defining the visual layer that will host the images

The AdornmentLayerDefinition is a private field but is accessible within the extension as it is exported via MEF. By specifying the name of "FestiveAdornments," we will reference it in other classes. By specifying that it comes after the predefined Text layer, it will appear on top of all the content in the file/editor. The editor has three built-in layers: text, caret, and selection. If we wanted everything in the layer to appear under the editor's other contents, we could specify the Order as coming Before the Selection.

Creating the class that displays the image

The final part of this class is the implementation of the TextViewCreated method. Visual Studio calls this and passes a reference to the IWPFTextView interface. We'll pass this to the control that displays the mistletoe image.

Displaying the mistletoe image

The MistletoeAdornment class handles the creation and positioning of the mistletoe image.

When the class is created, it:

  • creates the BitmapImage class that will display the png file.
  • specifies which layer to add the adornment to.
  • subscribes to LayoutChanged events of the WpfTextView so that we can redraw it in the middle of the top of the screen whenever the window size changes.

If we debug the project, a new experimental instance of Visual Studio is opened with our extension installed. If you then open any document file, you will see the mistletoe added in the middle, at the top of the screen.

screenshot of Visual Studio showing the mistletoe adornment

Displaying the holly images

We now need to create four new classes to create the four holly image. We could use one class that creates and positions multiple images, but as the classes are so simple, I find it easier to debug and maintain them as separate classes.

We'll call these classes TopLeftHollyAdornment, TopRightHollyAdornment, BottomLeftHollyAdornment, and BottomRightHollyAdornment.

These classes can all be the same as MistletoAdornment.cs but with three differences:

  1. The fields containing the height and width with which to display the images.
  2. The name of the file used when creating the BitmapImage.
  3. The code to position the images.
The code for the positioning of the images is this.

The repetition in these classes makes them a suitable candidate for abstracting the commonality, but this is left as an exercise for you if you'd like to do this.  

We now need to tell the creation listener to create the new classes.

When this is debugged, we see all four images.

Visual Studio editor with holly in each corner and mistletoe at the top

Adding Intra-text adornments

We can now add additional images between some of the text in the editor.

We'll start by adding some images to the Images folder and again setting the Include in VSIX property to true.

Christmas treesanta facesnowflakesnowmanpresent

The aim is to put these images next to words of between three and seven characters in length.

The extensibility workload includes an item for creating an Editor Text Adornment. However, it is not suitable for the complexity of our scenario.

Instead, we'll take inspiration from one of the VSSDK Extensibility Samples.

Specifically, we'll reuse the IntraTextAdornmentTagger and RegexTagger classes.

Our code will use two taggers. A tag is a way of associating some data with a location (or span) in the text. A Tagger is responsible for creating tags.

We need the first tagger to look through the text to find places to add the images. It will use a regular expression to find those locations and so will be based on the RegexTagger class.

The second tagger will be responsible for drawing creating tags that show where to draw the image adornments. This will be based on the IntraTextAdornmentTagger class.

Tagging where to put the images

The first thing we need to do is to tell Visual Studio that we will provide an ITagger that will produce FestiveImageTags. This is done with the FestiveImageTaggerProvider.

Next, we need to define the FestiveImageTagger. Most of the work this class does is inherited from RegexTagger, but we need to specify the Regular Expression (Regex) to identify where we want to put the tags/images.

The final thing we need to create the tags is the tag definition itself. FestiveImageTag implements the ITag interface, but this is used purely for identification and does not contain any functionality. The only thing the tag needs is the "term" or word matched by the regular expression.

If we ran the code now, we wouldn't see anything. This is because (most) tags by themselves do not cause any UI to be displayed. (Notable exceptions to this are the OutliningRegionTag and the ErrorTag, but we are not using them here.)

Putting images where there are tags

As with creating the tagger earlier, we first need a provider to tell Visual Studio to create the tagger. FestiveImageAdornmentTaggerProvider tells Visual Studio that in text documents, it will create a FestiveImageAdornmentTagger that will create IntraTextAdornmentTag where there are FestiveImageTag tags.

FestiveImageAdornmentTagger gets most of its logic by inheriting from IntraTextAdornmentTagger and specifies how to place a FestiveImageAdornment where there is a FestiveImageTag.

FestiveImageAdornment is just an Image with a bit of extra logic where we specify the image's path to use, which is done based on the length of the term.

This might seem complicated, but it allows functionality to be clearly separated into different classes.
In summary, the process works like this:

  1. The FestiveImageTaggerProvider tells Visual Studio to create a FestiveImageTagger for all text documents, and in turn, that will create FestiveImageTags.
  2. The FestiveImageTagger watches the changing text and adds a FestiveImageTag to each location in the document where we want to add an image.
  3. The FestiveImageAdornmentTaggerProvider tells Visual Studio to create a FestiveImageAdornmentTagger for all text documents and that will create tags of type IntraTextAdornmentTag where there are FestiveImageTags. (As created separately.)
  4. The FestiveImageAdornmentTagger creates (and updates) instances of FestiveImageAdornment within the document, in the location specified in the FestiveImageTag, and these are the displayed images.

The result of all this is that festive images will be added within the text of a document.

Visual Studio editor showing all the adornments created in this article


Practical uses of editor adornments

I have previously made several extensions (for more serious purposes) that use the techniques shown above. 

Real extensions using viewport adornments

These two extensions extend the editor by adding adornments to the viewport.

Show Selection

This extension displays the start and end positions of the current text selection in the top right-hand corner of the window.
The need to know this is niche but the ability to create an extension that displays this when needed, has saved hours of trying to manually determine how the location of specific points within a file.

Visual Studio editor window showing the selected position in the corner adornment

Get it from the Visual Studio Marketplace or view the source on GitHub.

Watermark

This extension allows the display of a customizable, text-based watermark on the editor. This is useful for ensuring that specific information (such as a name, URI, or email address) is always available to someone else viewing the screen. It is intended for use in demonstrations at conferences/meetups or while streaming. The content, size, colors, and position of the text are all configurable.
The watermark (my Twitter handle - @mrlacey) is highlighted in a red oval in the image below.

The Visual Studio editor showing a watermark

This extension is available from the Visual Studio Marketplace, and the code is on GitHub.

Real extensions using text-based adornments

These three extensions include f

Comment Links

This extension makes it possible to navigate between files of any type or language by placing a prefix of "Link:" before the filename in the comment. When this is done it adds a button that, when clicked, will navigate to that file. It can also jump to specific line numbers or instances of a specific piece of text within the file.
This was created to make it possible to easily navigate within projects that use different languages and so Visual Studio's built-in functionality for navigating to types doesn't work.

partial screenshot showing a button added into a comment

This extension is available from the Visual Studio Marketplace, and the code is on GitHub.

String Resource Visualizer

This extension displays the value of localized strings next to where they're used in source code. It works by identifying the use of values from a resource file (.resx or .resw) and displays the localized value above the usage. Configurable options support showing the default translation of that of a specific culture. This extension exists to help developers confirm that they are using the right value in the right place. It works with the ResourceManager and the ASP.NET Localizer.

This extension is slightly different from the above as it places the adornment above the text.

screenshot showing the values of string resources being displayed above where they're used

Examples of resources being shown when used via the ASP.NET Localizer

This extension is available from the Visual Studio Marketplace, and the code is on GitHub.

Const Visualizer

This is a companion extension to the String Resouce Visualizer. Rather than displaying resources, it displays the values of constants above the places where they're used.
This can be helpful to verify that the value of the constant you are using has the value you expect or intend.

screenshot showing examples of constants being displayed

This extension is available from the Visual Studio Marketplace, and the code is on GitHub.


Extending the Festive Editor code

There are lots of ways you can extend the above code. I've demonstrated a couple of examples in this video


Congratulations on making it this far. If you try extending or customizing this code for your own purposes I'd love to see the results. Share them in issues on GitHub or via Twitter.

If you're interested, you can find all the extensions I've made on the Marketplace.



Saturday, October 24, 2020

Rethinking open-source priorities - what is my time worth to me?

One day into trying to fix an issue I wondered if I was using my time wisely. Two days after that, and when I'd finally found the solution, I'm certain I hadn't been using my time wisely.

⏰⏲⏱

Cliche
Photo by CharClarPhoto - https://www.flickr.com/photos/charclarphoto/42437342612/

One of the things I like about contributing to open-source projects is that I can choose my priorities.

My thinking goes or rather went, that if I'm giving my time for "free" I should get to choose what I work on. I'm starting to think this isn't the best for me, or the projects I'm contributing to.

Back to the scenario, I started with.

One day into debugging the issue (an automated UI test that would fail periodically for no obvious reason) and I considered giving up. There were two things that kept me going:

  • I was really keen to understand the underlying issue.
  • I'd committed to fixing the bug. 
The bug was reported by a member of the project's core team and I'd created the test originally. I felt a personal responsibility to get it working. The bug was also something I (originally) thought I could fix quickly. Having the core team (who are paid to work on the project) spend their time on this didn't feel like a good use of their time.

Reflecting back on this, I was making a few (common?) false assumptions:
  • My time was worth less than those people paid to work on the project.
  • My time doesn't matter as it's just an open-source contribution. (I'm not being forced to do this.)
  • Because I'd started it I need to finish it.
  • Any external contribution to an open-source project is valid.
If this had been paid work, I would have stopped before the end of the first day working on this and said it wasn't worth the effort. If this had been my own open-source project I would probably have stopped then too. It wasn't worth the effort to spend more time trying to fix the issue. Having to occasionally rerun a test because of a false negative wasn't worth spending multiple days of effort. That time could have been used on something much more productive.
I would have been appalled to hear of someone being paid to work on the problem keep going for so long. So, why did I think it was ok for me to keep spending my unpaid time on it?

If you've read this far and think I was foolish and should have known better and stopped sooner. I agree.
Clearly, I need to reflect on this and better prioritize what I work on.

However, I think this highlights some important questions for people who maintain, lead, manage. or otherwise, influence people who contribute to projects. I'm thinking particularly of open-source projects but I suspect the same applies to closed projects within an organization too.
  • How do you ensure that all contributors are making the best use of their time?
  • How do you ensure an external contributor is doing something that is a good use of their time?
  • How do you prevent external contributors from becoming demoralized when stuck on tricky problems?
  • If you want external contributors, what are you doing to attract and keep them?

I think these questions matter because:
  • For paid workers, you want to ensure that the money spent on their time is being used effectively and efficiently.
  • For volunteers, you want to value and respect the gift of their time and ensure it is being used wisely.
  • For everyone, you want to make sure that no-one is stuck on something they should re-evaluate, abandon, or ask for help with.
    Previously I would have relied on people to speak up when they're stuck but this experience demonstrates that I don't always do this. So I shouldn't expect this from others.
  • For everyone involved, you want them to feel valued, appreciated, and that they're making valuable useful contributions.
    Some paid contributors will be happy to turn up, do something, and get paid without thinking about what they're doing and the wider consequences. But I expect having such people on a project that seeks open-source contributions can be a turn-off for would-be volunteer contributors.

Managing projects with both paid and volunteer contributors can be very tricky. I wonder if there are lessons from charities or other organizations that have both paid staff and volunteers which would be useful for those creating software this way?

If you have any thoughts on this, I'd love to hear them.
They could be on how you prioritize and know when to stop, re-evaluate, and when to keep going. Or maybe you have some thoughts about how project leaders/maintainers/managers can ensure that all contributors (paid or not) are making the best use of their time. Both personally and with regards to contributing to a project.

For me, the lesson I'm going to try and take forward is to think about giving my time to an open-source project and then focusing on what the best thing is I can do with that time. I'm going to try and put that time decision before I commit to fixing a bug or adding a feature.

post-script.
Yes, I did finally solve the issue. It was a timing issue (as they often are) relating to a light-dismiss dialog not always being closed. It's interesting, to me, to know this but was it worth two days of my time to find this out? Probably not. Would I have felt bad charging for my time to fix this if I was being paid? Yes.

Friday, October 09, 2020

6 tips for contributing to Open Source

 The following is based on a presentation I gave on the September 2020 WinUI community call.


Here are my tips

  1. Don't start with a Pull Request
  2. Follow the project's conventions
  3. Assume positive intentions
  4. Explain why. Don't say "should"!
  5. Focus
  6. Everything helps


Don't start with a Pull Request

If you're doing anything more complicated than fixing a typo or small spelling mistake, don't start with a pull request.
Engage with the project maintainers before you start doing any work.

You don't want to spend time on something that isn't wanted or that someone else is already working on. Nor do you want to build a solution that doesn't fit with what else is going on with the project.
It may also be beneficial to discuss possible ways to make the change, fix the bug, or add the proposed feature. You'll want to make the best use of your time, and maintainers or other people working on a project may have ideas and suggestions to help you.

You can "engage" with the appropriate people by creating an issue (if it's something new), commenting on an issue (if there is already on related to the work you want to do), commenting on a discussion, message board, email list, chatroom, or wherever else is appropriate for that project.
Aim to try and work the same way as others on that project already do.

Follow the project's conventions

Most projects include a document on how to contribute. Most of them include a note about not starting with a pull request. But there's more in there too. If a project has one, be sure to read the contributing.md document and follow what's written there.
If a project doesn't have a guide to contributing, ask how to get involved. And, maybe suggest a guide to contributing too.

As a general rule, code is easier to understand (and therefore review and maintain) if consistent in style, structure, and conventions. Anything you contribute should look like it belongs with the rest of the codebase.
Consistency applies to documentation too. It can be distracting for the reader when documentation uses differing tenses, styles, terminology, etc.

Many projects also use templates and checklists when creating issues and submitting pull requests. Always strive to provide the information and complete the desired tasks.

This isn't being done to be difficult.

Assume positive intentions

Projects ask for information because it helps. They're not asking for it to be difficult.
 
Project maintainers don't want you to waste your time. Also, they want to make the best use of their time. They ask for specific information to evaluate and accept a change or understand an issue. They don't do it to waste your time.

This point goes both ways.
Project maintainers need to remember that when an issue is raised with minimal details, it's not because someone is being difficult or lazy. They may not have been able to provide more information. They may not even speak the same language. 
Be kind.

Explain why. Don't say "should"!

If raising an issue, explain why you want a change, or how a new feature will help you. This helps others understand and allows appropriate prioritization.

Never say, "you should make it do X" without explaining why. 
I'm sure your opinions and ideas are great, but you need to do more than state them.
Is this currently causing you a problem? Or is it just something you think would be a "nice to have"? Why you're asking for or suggesting something can be essential to know.

Focus

And if you're raising issues about problems or suggesting new features, create separate issues for each problem or idea.

Breaking work down into discrete areas can help with understanding, prioritization, and associating changes.

It's much easier to triage and manage work when an issue only lists one problem.
It's easier to review a change that fixes one bug or adds one feature.

It's also useful when discussions remain focused.
Depending on the project, it may or may not be appropriate to have side discussions in issues or comments. I want to be more involved with several open-source projects, but I can't filter out all the seemingly unrelated discussions and so am unable to follow all the relevant discussions that occur.
Follow the conventions of the project regarding side discussions. 

Everything helps

The success of very few projects is predominantly decided by the code. Many other factors play their part, and you can contribute to these too.


This includes writing, expanding, or translating documentation. - There are projects I contribute to where they don't need other people writing code, but I can make a valuable contribution by writing docs.

The same goes for testing. - There are projects where others are paid to write code, but I can come in as an external contributor and make significant, valuable contributions by creating tests.


Again, there are projects where I add value by asking questions.

  • What about people who are using this for the first time?
  • Did you consider X?
  • Why did you do it that way?

This can be informal or as part of a code review.


Bringing different perspectives and experiences helps create something useful to more people and a wider variety of people.


Everything helps.


You can also support projects in other ways. For examples, see https://rapidxaml.dev/support


Financial support can be great if you can provide it, but not every project needs it.

Even if you can't provide a financial contribution, there are ways to support projects you use and value.

  • Leave a star on GitHub.
  • Leave a review or a star rating.
  • Spread the word through a tweet, blog post, stream, video, or whatever you use.


Feedback can be really encouraging for people investing in the creation of open-source projects and is a reminder that their effort is valued and appreciated.


Show you care. Show your support.




Monday, September 28, 2020

Living the open-source Utopian dream

With everything going on in the world, I thought it would be worth sharing a positive story about working on open-source projects and a Utopia where everyone works together to make software that benefits the people who use it.

This story relates to the Rapid XAML Toolkit. If you're not familiar with the project, it's is a collection of tools to help developers building apps with XAML inside Visual Studio.

Recently (a Friday), I discovered that the functionality that works with files being dragged from Solution Explorer and dropped in the editor had stopped working in the latest versions of Visual Studio.

I raised an appropriate bug report and posted a few messages to people who may be able to help and/or who use the same functionality too.

By Wednesday morning my time (noting that Monday was a public holiday in the USA) a member of the Visual Studio team had explained that what I was seeing was a deliberate change in behavior. They added public documentation justifying the change and why it had been made. They also gave details of an alternative approach to get the same underlying behavior. Best of all, they raised a PR against my repository, which included the change in approach to get the same result.


Separately, I have a GitHub action that checks all the URIs in documentation (and elsewhere) are correct and are not "dead links". Over the same weekend, this started failing in an inconsistent way that I could not explain.

I then raised an issue on the repository of the action but wasn't overly confident about anything happening.

My Wednesday evening the author of the action had fixed the problem, released a new version, and created a PR for my repository to switch to the new version.



These two instances demonstrate and reinforce my idea of open source being about "everyone working together, so the world gets better software."  The other two people didn't have to make changes and create Pull Requests, but by doing so they've helped me and the people who use the toolkit.


Tuesday, September 22, 2020

What's in the Universal device family API contracts

This post exists to list information no longer documented by Microsoft.

---


This page contains a list of all of the API contracts that are part of the Universal device family. These API contracts are implemented by all Windows 10 operating system editions. By default, Microsoft Visual Studio specifies **Windows.Universal** as the target device family in the app package manifest file for UWP apps. To read more about device families, check out the Device families overview page.


Version 10.0.18362.0

Windows.AI.MachineLearning.MachineLearningContract, version=2.0

Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract, version=2.0

Windows.ApplicationModel.Calls.Background.CallsBackgroundContract, version=2.0

Windows.ApplicationModel.Calls.CallsPhoneContract, version=5.0

Windows.ApplicationModel.Calls.CallsVoipContract, version=4.0

Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract, version=2.0

Windows.ApplicationModel.SocialInfo.SocialInfoContract, version=2.0

Windows.ApplicationModel.StartupTaskContract, version=3.0

Windows.Devices.Custom.CustomDeviceContract, version=1.0

Windows.Devices.DevicesLowLevelContract, version=3.0

Windows.Devices.Printers.PrintersContract, version=1.0

Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract, version=3.0

Windows.Devices.SmartCards.SmartCardEmulatorContract, version=6.0

Windows.Foundation.FoundationContract, version=3.0

Windows.Foundation.UniversalApiContract, version=8.0

Windows.Gaming.XboxLive.StorageApiContract, version=1.0

Windows.Graphics.Printing3D.Printing3DContract, version=4.0

Windows.Networking.Connectivity.WwanContract, version=2.0

Windows.Networking.Sockets.ControlChannelTriggerContract, version=3.0

Windows.Services.Maps.GuidanceContract, version=3.0

Windows.Services.Maps.LocalSearchContract, version=4.0

Windows.Services.Store.StoreContract, version=4.0

Windows.Services.TargetedContent.TargetedContentContract, version=1.0

Windows.System.Profile.ProfileHardwareTokenContract, version=1.0

Windows.System.Profile.ProfileSharedModeContract, version=2.0

Windows.System.Profile.SystemManufacturers.SystemManufacturersContract, version=3.0

Windows.System.SystemManagementContract, version=6.0

Windows.UI.ViewManagement.ViewManagementViewScalingContract, version=1.0

Windows.UI.Xaml.Core.Direct.XamlDirectContract, version=2.0


Version 10.0.17763.0

Windows.AI.MachineLearning.MachineLearningContract, version=1.0

Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract, version=2.0

Windows.ApplicationModel.Calls.Background.CallsBackgroundContract, version=1.0

Windows.ApplicationModel.Calls.CallsPhoneContract, version=4.0

Windows.ApplicationModel.Calls.CallsVoipContract, version=4.0

Windows.ApplicationModel.CommunicationBlocking.CommunicationBlockingContract, version=2.0

Windows.ApplicationModel.SocialInfo.SocialInfoContract, version=2.0

Windows.ApplicationModel.StartupTaskContract, version=3.0

Windows.Devices.Custom.CustomDeviceContract, version=1.0

Windows.Devices.DevicesLowLevelContract, version=3.0

Windows.Devices.Printers.PrintersContract, version=1.0

Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract, version=3.0

Windows.Devices.SmartCards.SmartCardEmulatorContract, version=6.0

Windows.Foundation.FoundationContract, version=3.0

Windows.Foundation.UniversalApiContract, version=7.0

Windows.Gaming.XboxLive.StorageApiContract, version=1.0

Windows.Graphics.Printing3D.Printing3DContract, version=4.0

Windows.Networking.Connectivity.WwanContract, version=2.0

Windows.Networking.Sockets.ControlChannelTriggerContract, version=3.0

Windows.Services.Maps.GuidanceContract, version=3.0

Windows.Services.Maps.LocalSearchContract, version=4.0

Windows.Services.Store.StoreContract, version=4.0

Windows.Services.TargetedContent.TargetedContentContract, version=1.0

Windows.System.Profile.ProfileHardwareTokenContract, version=1.0

Windows.System.Profile.ProfileSharedModeContract, version=2.0

Windows.System.Profile.SystemManufacturers.SystemManufacturersContract, version=3.0

Windows.System.SystemManagementContract, version=6.0

Windows.UI.ViewManagement.ViewManagementViewScalingContract, version=1.0

Windows.UI.Xaml.Core.Direct.XamlDirectContract, version=1.0


Version 10.0.17134.1

Windows.AI.MachineLearning.Preview.MachineLearningPreviewContract, version=1.0

Windows.ApplicationModel.Calls.CallsVoipContract, version=3.0

Windows.ApplicationModel.SocialInfo.SocialInfoContract, version=2.0

Windows.ApplicationModel.StartupTaskContract, version=3.0

Windows.Devices.Custom.CustomDeviceContract, version=1.0

Windows.Devices.DevicesLowLevelContract, version=3.0

Windows.Devices.Printers.PrintersContract, version=1.0

Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract, version=3.0

Windows.Devices.SmartCards.SmartCardEmulatorContract, version=5.0

Windows.Foundation.FoundationContract, version=3.0

Windows.Foundation.UniversalApiContract, version=6.0

Windows.Gaming.XboxLive.StorageApiContract, version=1.0

Windows.Graphics.Printing3D.Printing3DContract, version=4.0

Windows.Networking.Connectivity.WwanContract, version=2.0

Windows.Services.Store.StoreContract, version=3.0

Windows.Services.TargetedContent.TargetedContentContract, version=1.0

Windows.System.Profile.ProfileHardwareTokenContract, version=1.0

Windows.System.Profile.ProfileSharedModeContract, version=2.0

Windows.UI.ViewManagement.ViewManagementViewScalingContract, version=1.0


Version 10.0.16299.0

Windows.ApplicationModel.Calls.CallsVoipContract, version=2.0

Windows.ApplicationModel.SocialInfo.SocialInfoContract, version=2.0

Windows.ApplicationModel.StartupTaskContract, version=2.0

Windows.Devices.Custom.CustomDeviceContract, version=1.0

Windows.Devices.DevicesLowLevelContract, version=3.0

Windows.Devices.Printers.PrintersContract, version=1.0

Windows.Devices.SmartCards.SmartCardBackgroundTriggerContract, version=3.0

Windows.Devices.SmartCards.SmartCardEmulatorContract, version=5.0

Windows.Foundation.FoundationContract, version=3.0

Windows.Foundation.UniversalApiContract, version=5.0

Windows.Gaming.XboxLive.StorageApiContract, version=1.0

Windows.Graphics.Printing3D.Printing3DContract, version=4.0

Windows.Networking.Connectivity.WwanContract, version=1.0

Windows.Services.Store.StoreContract, version=2.0

Windows.Services.TargetedContent.TargetedContentContract, version=1.0

Windows.System.Profile.ProfileHardwareTokenContract, version=1.0

Windows.System.Profile.ProfileSharedModeContract, version=2.0

Windows.UI.ViewManagement.ViewManagementViewScalingContract, version=1.0


Version 10.0.15063.0

Windows.ApplicationModel.Calls.CallsVoipContract, version=1.0

Windows.ApplicationModel.SocialInfo.SocialInfoContract, version=2.0

Windows.Devices.DevicesLowLevelContract, version=3.0

Windows.Devices.Printers.PrintersContract, version=1.0

Windows.Foundation.FoundationContract, version=3.0

Windows.Foundation.UniversalApiContract, version=4.0

Windows.Graphics.Printing3D.Printing3DContract, version=3.0

Windows.Networking.Connectivity.WwanContract, version=1.0

Windows.Services.Store.StoreContract, version=2.0

Windows.Services.TargetedContent.TargetedContentContract, version=1.0

Windows.System.Profile.ProfileHardwareTokenContract, version=1.0

Windows.System.Profile.ProfileSharedModeContract, version=2.0

Windows.UI.ViewManagement.ViewManagementViewScalingContract, version=1.0


Version 10.0.14393.0

Windows.ApplicationModel.Calls.CallsVoipContract, version 1.0

Windows.ApplicationModel.SocialInfo.SocialInfoContract, version 1.0

Windows.Devices.DevicesLowLevelContract, version 2.0

Windows.Devices.Printers.PrintersContract, version 1.0

Windows.Foundation.FoundationContract, version 2.0

Windows.Foundation.UniversalApiContract, version 3.0

Windows.Graphics.Printing3D.Printing3DContract, version 3.0

Windows.Networking.Connectivity.WwanContract, version 1.0

Windows.Services.Store.StoreContract, version 1.0

Windows.System.Profile.ProfileHardwareTokenContract, version 1.0

Windows.System.Profile.ProfileSharedModeContract, version 1.0

Windows.UI.ViewManagement.ViewManagementViewScalingContract, version 1.0


Version 10.0.10586.0

Windows.ApplicationModel.Calls.CallsVoipContract, version 1.0

Windows.Devices.Printers.PrintersContract, version 1.0

Windows.Foundation.FoundationContract, version 1.0

Windows.Foundation.UniversalApiContract, version 2.0

Windows.Graphics.Printing3D.Printing3DContract, version 2.0

Windows.Networking.Connectivity.WwanContract, version 1.0


Version 10.0.10240.0

Windows.Foundation.FoundationContract, version 1.0

Windows.Foundation.UniversalApiContract, version 1.0

Windows.Networking.Connectivity.WwanContract, version 1.0