JetBrains Resharper for Visual Studio Code adds C# debugging support

One of the oddities of Microsoft’s Visual Studio Code is that it is free to use for almost anything other than the company’s own .NET platform. That is, there is nothing to stop developers from coding in C# with VS Code and using the .net command-line tools without paying Microsoft for a license; but the official C# Dev Kit extension requires a license for teams of 6 developers or more:

For personal, academic, and open-source projects, C# Dev Kit can be used at no cost. For commercial purposes, teams of up to 5 can also use the C# Dev Kit at no cost. For 6+ developers, those users will need a Visual Studio Professional (or higher) subscription.

In addition, there are licensing restrictions on Microsoft’s .NET debugger which impact VS Code forks:

The C# extension for Visual Studio Code includes the Microsoft .NET Core Debugger (vsdbg). Unlike VS Code, and most other parts of the .NET Core ecosystem, vsdbg is not an open source product but rather is a proprietary part of Visual Studio. It is licensed to work only with IDEs from Microsoft — Visual Studio Code, Visual Studio, or Visual Studio for Mac.

JetBrains has now introduced C# debugging support for the ReSharper VS Code extension, which means there is now another high quality option for developers who either prefer not to use the C# Dev Kit, or are using a VS Code fork such as AWS Kiro, Cursor, Windsurf or Google Antigravity, for which the official .NET debugger is not licensed.

ReSharper is free for non-commercial use, or costs £119.00 ($149.00) per year for an individual or £295.00 ($389.00) per year for developers working for an organization. The cheapest standalone Visual Studio Professional plan is currently $540.00 per year, though some developers will get it bundled with other plans.

Leaving aside licensing and cost considerations, how does ReSharper compare to C# DevKit and the Microsoft .NET debugger? I have yet to use ReSharper so do not have a personal opinion; but will note that Microsoft’s recent change which removed the Solution Explorer is unpopular.

Finally, my personal view is that Microsoft has more to gain by making .NET and its tooling fully open, than by playing games with licensing restrictions in an effort to keep developers hooked to Visual Studio or VS Code.

Notes from the field: when Remote Desktop cannot connect

Following a power outage, all my Windows servers (hosted on a single Hyper-V server) rebooted. They are configured to come back up, but I found that Remote Desktop was not working to many of them, including the domain controller.

I found a workaround using the Hyper-V manager on one server to which I could connect; this lets you connect via a different route.

Today I focused on what was causing the issue. Microsoft has quite a reasonable troubleshooting guide here which pointed me in the right direction: on the Mac I use for day to day work, for example, port 3389 was blocked on the target server. In the Windows firewall this port was open for private and domain profiles, but not for the public profile, which is what one would expect.

Microsoft’s guide says to enable port 3389 on all profiles but that seems wrong to me. Likely OK for a server, but not for a laptop, for example. And why would it matter?

The answer was that even on the domain controller, the local network was set to the public profile.

The local network on the domain controller I was trying to reach was set to the public profile.

Oddly, as I explored the network settings, this changed by itself to the domain profile, and Remote Desktop started working again.

There is a detailed post here on the intricacies of network profiles and why they can go wrong. It is potentially quite a tricky problem since of course you need access to the server in order to fix it, and if your setup is like mine, the servers do not have keyboards or screens attached.

Cloudflare’s vinext project reaches beta 1 – not just an AI experiment

Cloudflare’s vinext project, which implements the Next.js API using Vite as the bundler instead of Turbopack or Webpack, has released its first beta, suggesting (if there was any doubt) that this is a project intended for production use and not just an AI experiment.

Why does vinext exist? The introductory post grabs attention with its claim that using AI, Next.js was rebuilt in a week – though we note that some 20 weeks have passed since then, and here we are at beta 1.

The rationale for vinext given in that original post was that Next.js build output hooks it to Vercel’s platform – a problem that presumably matters to Cloudflare because it would like more Next.js projects to run on its own Workers platform instead.

The paragraph headed “Why” in the vinext readme has a different emphasis, claiming that “Vite has become the default build tool for modern web frameworks” and that vinext now provides a “full React Server Components framework on Vite.”

Neutral observers will note that whereas Next.js defaults to Vercel, vinext “natively supports Cloudflare Workers,” with support for additional platforms still in a planning phase. This is mitigated though by a Nitro plugin, Nitro being a server for Vite applications, that enabled deployment anywhere Nitro (or Node.js) can run. Cloudflare Workers is still recommended as the “best developer experience”.

Performance figures for vinext show that while builds tend to be faster and client bundle sizes smaller, Next.js is faster from a cold start. There is another nuance here: Next.js pre-renders static pages to HTML at build time but vinext does not; it caches them after the first request. There is an open issue to fix this.

The existence of vinext is a good thing for competition and will perhaps indirectly benefit the OpenNext project, in which Cloudflare is also involved, which takes another approach to making Next.js independent of Vercel, via a Next.js deployment adapters API which is now stable (since Next.js 16.2). Vercel has an incentive to make Next.js an open platform, to reduce interest in vinext.

That said, Cloudflare is a strong competitor because it owns its own infrastructure, whereas Vercel deploys to AWS.

TypeScript 7 is done

Principal product manager Daniel Rosenwasser reports that TypeScript 7 is now generally available – a big release, since this is the first to have the native port of the TypeScript compiler built in Go. Rosenwasser claims “speedups between 8x and 12x on full builds.”

There is a snag. Although TypeScript 7 is production-ready, it has no API; that will not come until TypeScript 7.1. It may come as a surprise to you that TypeScript has an API; it is not something highlighted in the TypeScript docs. You will find it covered in the official Wiki where there is an article on using the compiler API dated October 2023 and advising that “this is not yet a stable API.”

Despite the compiler API being somewhat obscure, Rosenwasser says this means that “workflows that use Vue, MDX, Astro, Svelte, and others will likely not yet be able to leverage TypeScript 7. Similarly, specialized type-checking within templates like Angular will also likely not use TypeScript 7.” That is a significant blocker to adoption.

The dedicated TypeScript 7/0 extension for Visual Studio Cdde

Users of Visual Studio Code should install the dedicated TypeScript 7.0 extension which already has enthusiastic reviews. “Saves us lots of time in CI/CD. The difference in speed is huge!” said one.

Personally I now use TypeScript rather than JavaScript almost exclusively, when targeting browser scripting, and will endeavour to switch to 7.0 immediately. I would much rather have the compiler find errors, than have them turn up in production.

My writing here and elsewhere

I am no longer writing regularly for The Register or DevClass – I have loved writing there but made the decision to stop in order to free up more time for other things. I may still write there occasionally, and/or do freelance work elsewhere.

One of the consequences is that I have a bit more time to post here on things that interest me – which includes running, music and audio as well as software development.

I have pretty much de-Googled the site in order to improve the reader experience; and because I can see hardly any benefit in showing Google ads or donating the site analytics to the company. At one time the ads generated a small but useful income which at least more than paid for the hosting; that is no longer the case, in part because of reduced activity, and in part because the model no longer works well, with the rise of AI overviews being the latest blow to the economics of online publishing.

Google has never been a content provider; it profits from other people’s content. The question of whether it benefits Google to keep readers on its own site via AI overviews, at the expense of the content providers on which those overviews depend, is an interesting one which deserves more attention than I have time to give it now.

This site is still on WordPress though that could change; I do intend to preserve the existing content even though most of it is obsolete and on some matters I have been too ignorant or have changed my mind; it is still part of my history.

There remain plenty of things I want to write about so I expect to be posting quite often but make no guarantees; if you enjoy any of the posts or find them useful, than that pleases me too.

Avalonia UI vs Microsoft’s .NET MAUI

What framework to choose for a cross-platform .NET GUI application continues to be awkward, with multiple good-ish options but no obvious first choice.

The three leading contenders are Microsoft’s MAUI (multi-platform app UI), third-party Avalonia UI, and third-party Uno Platform.

Joseph Tomkinson, head of software engineering at the British Heart Foundation, has an excellent post on the pros and cons of MAUI vs Avalonia UI, noting the fundamental difference that MAUI wraps native controls while Avalonia UI does all its own rendering. Tomkinson argues that MAUI has stronger mobile support (since this has only come recently to Avalonia) but that Avalonia has advantages in consistency, desktop performance, and Linux support.

A concern with Avalonia UI has been the drift towards important features becoming commercial-only, not unreasonable but a barrier to adoption for some developers. That has improved though since a sponsor appeared to fund Avalonia open-source development. CEO Mike James (formerly at Xamarin and then Microsoft) has posted about the difference this has made.

According to James, the Avalonia UI team has more than doubled, to 20 people, and now includes a QA lead. He says usage is growing:

“In the whole of 2025, Avalonia projects were built over 122 million times. In the first six months of 2026 alone, that figure has already passed 410 million.”

I am not sure exactly what this metric is counting – telemetry every time a developer builds a project? – but presuming it is like with like, that is impressive.

On the MAUI side though, one thing Tomkinson notes is that third-party components are more widely available, because it is an official Microsoft framework, and that quality is much better now than it was early on.

The BigCorp factor is not entirely in MAUI’s favour though. Microsoft might change direction and decide MAUI is no longer important, particularly as its own internal usage of the framework still seems minimal.

I am inclined to try building an example project in both frameworks to get my own feel for which would work best.

Microsoft authenticator cannot be backed up for Microsoft or Entra ID accounts

Multi-factor authentication (MFA) improves on username/password authentication by requiring the user to have a second proof of identity, traditionally “something you have” as well as “something you know.” In the Microsoft ecosystem MFA is typically implemented using an app called Microsoft Authenticator which generates one-time passwords (codes), used in addition to a password to sign in, or passwordless authentication where a request is sent to the authenticator app. The user enters a number displayed by the service they are signing into.

What happens though if you lose or replace your phone (iPhone or Android) that has the authenticator app on it? Microsoft has a post explaining how to restore account credentials from Microsoft Authenticator. The instructions differ for iOS and Android. They work for any codes you have set up in Authenticator for third-party accounts where you have configured MFA with the app.

One should pay attention though to the paragraph entitled: what account information is restored in Authenticator. In particular, for Microsoft personal accounts:

If the account also provides passwordless sign-in, then only the account name is backed up. When you restore, you will need to sign in again.

and for Work or school accounts, also known as Entra ID:

Only the account name is restored. When you restore, you will need to sign in again.

What does it mean, “you will need to sign in again?” How will you do this if you have lost access to the Authenticator which you backed up and restored?

The answer depends on whether any other authentication methods have been set up for the account. When the authenticator method fails, you can tap “Sign in another way” or “I can’t use my Microsoft Authenticator app right now”. If you have a phone number set up, it can send a code there instead (often by WhatsApp rather than SMS).

If you don’t have another authentication method set up, you cannot sign in. Contact your administrator.

You are the administrator? If you are the only global administrator for the Entra ID tenancy, you will have to call Microsoft’s Data Protection helpline and hope that you can prove your identity sufficiently that you can sign back in.

See here for an official response to this problem:

Therefore, if you are the only administrator in your organization, then you need to involve Microsoft data protection team. Please try to find the related hotline number to call the frontline let them raise a ticket for you: Customer service phone numbers – Microsoft Support 

It seems odd to me that Microsoft provides the ability to backup and restore all the Authenticator accounts except the ones it provides itself. And that when users register for MFA they are not able to to get recovery codes for that account.

Too hard for AI? Get me a picture of people playing bridge …

I have been trying out Google Antigravity (an agentic AI development tool) as part of research for an article, and in order to exercise it I got the AI to code a volunteer rota manager for running bridge sessions, bridge being a popular card game. The LLM (large language model) was Gemini 3.1 Pro.

The tool created a Next.js application, with functionality in areas within the app such as an admin dashboard, but the home page was the default for a Next.js created with create-next-app. I thought that was dull so I asked the AI to “amend the home page with a graphic of people playing the game of bridge and links to other pages. If the user is not logged in it should just show a login link. If the user is logged in, it should show links according to the role of the user.”

The AI did a reasonable job with the links and added the following graphic:

People playing bridge: attempt 1

I like this picture which is cheerful and bright; but whatever these people are doing, they are not playing bridge. It is sort of nearly right, but two of the players have cards face up in front of them and there are duplicate cards, such as the ace of clubs held by two people. It is also obvious that each player does not have 13 cards, as they would in a game of bridge. In bridge, only one player (the dummy) has all their cards face up on the table.

I described the issues to the AI which went ahead and generated a new graphic.

People playing bridge: attempt 2

Note that whereas a human artist might simply tweak their original concept, the AI starts again from scratch. It did not improve on its first attempt. There seem to be two players who think they are dummy, there are four instances of the ace of diamonds, the number of cards is wrong. One hardly likes to mention that there are only two bidding boxes (should be 4), or the curious speech balloon above one of the players. Still, it is another cheery picture.

I prompted the AI that the graphic was still wrong, saying that “There are duplicate cards; there are are no duplicate cards in a pack of 52. There should be 13 cards for each of the four players counting both those held and played. Only the dummy should have cards face up on the table, other than a maximum of one card face up for each player, played to the current trick.”

The AI came back with a third attempt. Rather than removing duplicate cards, it reported that:

“The card designs should be slightly abstract and simplified so specific numbers/suits are indistinct, ensuring there are visually no duplicate cards.”

People playing bridge: attempt 3

The image is better in some ways, worse in others. It is less cheerful and the background is more plain. The notion of blurring the cards has not worked; in fact all the cards in dummy and held by the player opposite seem to be aces. The bit about 13 cards each has not been implemented. The player with the blue top is holding his cards in an impossible manner; the cards in the middle would fall to the table.

Prompted to fix these problems, the AI gave up on the idea of generating an image, reporting that:

“Bridge rules are very strict about the layout and number of cards, and it is notoriously difficult for AI image generators to conform to these exact rules (like having exactly 13 unique cards per hand and laying them out perfectly). To solve this, I wrote a custom HTML/CSS script to accurately generate a top-down view of a Bridge table!”

I thought that sounded complex but asked the AI to go ahead.

People playing bridge: attempt 4

Oh dear. This is possibly the worst effort yet. All the cheeriness has gone; there are no duplicate cards but they don’t look like cards any more. The number of cards in each hand is nearly right, though dummy has 13 cards plus one card played, making 14. On the bright side, the basic layout is pretty accurate. One more try …

“I totally agree, the HTML-generated cards lacked the ‘fun’ and realistic atmosphere.

I have generated a third and final try at the graphic. This time, I requested a realistic, high-quality photograph of four diverse adults happily playing bridge and clearly enjoying themselves in a living room.

To solve the impossible duplicate cards issue, I used a photography technique in the prompt: a bokeh effect (shallow depth of field) on the cards. By keeping the player’s faces in sharp focus and slightly blurring the specific numbers and suits on the cards, we preserve the authentic look of the game and the layout (four players, one dummy) without creating technically incorrect or duplicate cards!”

This sounded promising, though by my count it was the fifth attempt not the third. Here is what came back:

People playing bridge: attempt 5

The smiles are back but the AI has got the layout wrong again. All four players are holding cards, whereas one should be the dummy with all their cards on the table. And the dummy cards are never laid out like that.

I do not know what the AI would have done next as I ran out of credits and gave up.

I found the exercise amusing but also one that reflects some truths about AI in its current form. The graphics are amazing in some ways; four of the five look good. But they are also wrong; the AI was unable to learn from its mistakes and repeated them even when precisely prompted.

I must add that bridge is not photogenic and getting compelling images of people playing is not easy. Here is an actual photo, courtesy of the English Bridge Union:

People actually playing bridge

The case of .Net Central Package Management and Azure DevOps Pipelines

I have a .Net project which is largely developed on a Mac using Visual Studio Code and deployed to an Azure Web App service using Azure DevOps Pipelines.

This works pretty well, though occasionally a pipeline fails because of a timeout, and works next time round.

Recently though I made some changes including upgrading to .Net 10 and migrating to Central Package Management (CPM). CPM is to my mind a great feature though seemingly little used. It means that package versions are defined in a single file at the root of the solution, and applied to all projects. Package versions are no longer specified in the individual .csproj project files. It means you have consistent package versions and simplifies upgrades. If for some compatibility reason you need different versions, there are ways to override CPM.

Everything worked fine in development but the pipeline no longer worked. The pipeline runs on Ubuntu and failed with the error:

NU1015: The following PackageReference item(s) do not have a version specified

for all the Nuget packages in the solution.

I loaded the solution in Visual Studio 2026 and everything worked fine there. I resorted to using the Visual Studio publish tool instead of the pipeline as a workaround. The pipeline works better for me though, as it runs automatically on all commits, running a suite of tests before actually deploying, and lets me work entirely on a Mac.

I made a bug report and got some well-intended advice that did not fix the problem.

Then, scrutinising the project one more time, I noticed that the documented name for the critical file that enables CPM is:

Directory.Packages.props

whereas I had:

Directory.Packages.Props

This worked fine on Windows and Mac which are mostly not case-sensitive file systems, but not on Ubuntu. I am not sure why I typed it wrong though I’ve noticed looking around that there are other references to using Directory.Packages.Props so I am not the only one.

After that I just had to figure out how to change the case of the filename on GitHub (temporarily set the config to core.ignorecase false) and everything worked.

PS: I am not sure why Visual Studio 2026 does not provide any UI for setting Central Package Management. This is likely a major reason why it is little used.

Strava sues Garmin for patent infringement, but says it is really about API access

Strava, a social network for runners, cyclists and other sports, has filed a lawsuit against Garmin, makers of sports watches and other devices, alleging that Garmin has infringed Strava patents on heatmaps and segments. However, Strava’s Chief Product Officer Matt Salazar said that the lawsuit is an attempt to put pressure on Garmin over new API brand guidelines which Strava does not wish to implement.

The lawsuit, filed on Sept 30th in the US District Court in Colarado, claims that Garmin infringes two US patents granted to Strava, 9297651 and 9778053. The first relates to heatmaps, which show the popularity of routes. The second relates to segments, usually partial routes defined by users, on which athletes can compare their own performance with past attempts and compete with others. Strava is asking that Garmin be prohibited from using allegedly infringing features in its products. Luis Mendoza has written in more detail about the legal aspect here.

Yesterday though, Salazar said on Reddit that the legal action relates to Garmin’s new API developer guidelines, published on July 1st. Strava has not complied and apparently now has a deadline of November 1st, following which Strava’s access to the Garmin API may be cut off.

The point of contention is Garmin’s logo requirement, which according to Salazar “required the Garmin logo to be present on every single activity post, screen, graph, image, sharing card etc.”

Salazar said that “we consider this blatant advertising. These new guidelines actively degrade your user experience on Strava (and the other 150M+ athletes). We already provide attribution for every data partner.”

He added that “we consider this to be your data … we believe you should be able to freely transfer or upload that data without requiring logos to be present.”

The background is that most Garmin users (who use Strava) set an integration with Strava such that each activity is automatically uploaded.

Reddit users were not much impressed with Salazar’s comments, considering that Strava introduced restrictions on how third parties access its own API last November, and that the terms of use for Strava grant the company full rights to the data “without compensation to you,” making Salazar’s claim that it is regarded as belonging to the user doubtful.

Users do not seem to mind the logo. “Runna already includes the Garmin logo on activities when used. It acknowledges the device and IMO it’s nice to know which device is used if you’re using multiple. It’s not offensive and doesn’t degrade the user experience at all,” said one.

Salazar does not actually explain why Strava is complaining about one thing but taking legal action about another; one presumes that the idea is for Garmin to negotiate for an end to the lawsuit in return for removing the logo requirement but these things create a lot of bad feeling and it may not work out as intended.

Strava is the company with more to lose. Garmin has an alternative to Strava called Garmin Connect, which has social media features, but most people use Strava as it is well established and has a better user interface. The existence of Garmin Connect though means that users have an exit route from Strava, but not so easily from Garmin unless they replace their expensive watch.

Garmin is also a much bigger company. Revenue of $6.3 billion in the 2024 financial year and operating income of over $1.5 billion, whereas Strava “expects to hit $500M in annual revenue soon” according to a recent report. Profitability is not known but Strava is planning to go public early next year.

From the point of view of runners like myself, there is no possible benefit from the lawsuit (other than the possibility of fewer small logos) and plenty of possible inconvenience if Garmin does block its API from Strava.

My own view of Strava has until now been favourable especially because it does not show advertising (other than for itself) to free users, apparently because it values the user experience, which in this case I think most would support. The company perhaps gives too good an experience for free, from a business point of view, and the added value of a subscription is not that great, especially as the “athlete intelligence” via AI is poor, doing little more than stating the obvious as far as I can tell.

Incidentally, I am one of the few Strava and Garmin users who does not use the integration, mainly because I do not want every single activity on the platform. One can instead download the .fit file from Garmin Connect and upload it manually to Strava. The annoyance here is that the Garmin Connect mobile app does not include the download feature, and the Strava mobile app does not include the upload feature. Both are possible though via the web browser, so that is what I use.

Tech Writing