Skip to main content

Posts

DSC 3.0: running your own PowerShell with getScript, testScript and setScript

Sooner or later you hit a setting that no DSC resource manages. A hosts file entry, a certificate with specific properties, some tweak that only exists as a PowerShell snippet on a wiki page. You know the PowerShell to fix it, but there is no resource to wrap it in. One way is to reach for Microsoft.DSC.Transitional/RunCommandOnSet . It runs a command during the set operation, and that is all it does. There is no test, so DSC cannot tell you whether the machine is in the desired state. But it is a good fit as a temporary transitional resource while migrating DSCv3 resources. There is another option: Microsoft.DSC.Transitional/PowerShellScript . It lets you bring your own getScript , testScript and setScript . Note: If you are new to DSC 3.0 check out my blog series about it: Getting started with DSC 3.0 – Part 1: What is DSC and what changed? Getting started with DSC 3.0 – Part 2: Managing a Windows service end to end Getting started with DSC 3.0 – Part 3: Capturin...
Recent posts

Letting GitHub Copilot drive your desktop with computer use

I'm a big fan of the Automations feature in the GitHub Copilot app. It allows me to focus on the most important stuff and I can schedule and delegate a lot of work in the background. Most of the time, these automations can interact with an API, a CLI or an MCP server. But what if you want to interact with a desktop application that only exists as a GUI, a legacy tool nobody wants to touch, a screen you have to click through by hand every week. That is the gap GitHub is trying to close with the recently introduced 'computer use' feature in the GitHub Copilot app and Copilot CLI. What is computer use? Computer use lets Copilot interact with desktop applications on your behalf. It reads the application content through the accessibility tree of your operating system and takes screenshots when it needs visual context. Then it can click controls, enter and edit text, press keys, scroll and drag. Some facts up front: It is in public preview since October 1, 2026 ...

SQL Server Full-Text Search: when a stop word broke our search

One of our users complained that the search functionality was broken. Searches that should have returned results came back empty. The cause turned out to be a single word: 'both'. If you are new to Full-Text Search, start with my previous post. It explains the building blocks I use below. The problem The search in our application is built on SQL Server Full-Text Search. The terms a user types are combined into a CONTAINS query. A simplified version looks like this: SELECT ProductId, Name FROM dbo.Products WHERE CONTAINS(Description, '"bike" AND "both"'); This returned no rows, even though we knew there were products matching both terms. Searching for "bike" alone worked fine. Looking for the cause The cause is simple:  Stop words Stop words are words that are not indexed because they are considered too common to be useful. SQL Server ships with a system stoplist per language, and 'both' is on the English one: S...

SQL Server Full-Text Search: an overview

Although we have ElasticSearch running in our environment, our most important search functionality is still handled by SQL Server. And no, it is not by writing a statement like WHERE Name LIKE '%term%' . That would probably work on a small table, but we have a lot of data to dig through, so we need something smarter than substring matching. SQL Server has a built-in answer for this: Full-Text Search . In this post I walk through the building blocks and the main features. In the next post I'll show what happened when a customer ran into a surprising side effect. Why do we need this? A LIKE with a leading wildcard can't use an index seek. SQL Server has to scan every row and compare strings. On top of that, LIKE knows nothing about language: searching for 'ride' won't find 'riding', and there is no concept of relevance. Full-text search works differently. It builds an inverted index: a list of words (tokens) and, for every word, the rows wh...

Reducing the size of your authentication cookie with ITicketStore

We are currently testing a new WAF for our organization. After activating it, we noticed that some requests never hit our server. Further investigation showed that the root cause was linked to our authentication cookies becoming to big. As the WAF had very strict limits configured, the request was blocked. The cause is how cookie authentication in ASP.NET Core works by default. The complete AuthenticationTicket (the claims, the properties and the tokens) is serialized, encrypted and put in the cookie. The bigger your identity, the bigger your cookie. Of course, we could just change the WAF configuration and increase the limits but isn't there a better way that allows us to limit the cookie size? Let's find out together... Keep the ticket on the server Cookie authentication has an extension point for this: ITicketStore . When you provide an implementation through CookieAuthenticationOptions.SessionStore , the ticket is stored server-side. The cookie only contains a se...

Napkin math: know what your system should do before you measure it

Last week I was evaluating some application performance characteristics with another architect. Our gut feeling told us that the numbers didn't make sense but we couldn't pinpoint why we had this feeling. This reminded me of a recent Pragmatic Engineer podcast episode with Simon Eskildsen (co-founder of turbopuffer, ex-Shopify). He was talking about a habit that fixes exactly this: napkin math . What is napkin math? Napkin math means estimating how a system should perform, using a few known numbers and some arithmetic. No code, no prototype, no load test. You work from first principles: how fast can this machine read memory, how long does a round trip to S3 take, what does a gigabyte cost? Simon turned this into a project. He collected the real numbers for latency, bandwidth and cost and kept them in a table on GitHub . Then he made flashcards for almost every cell, so he could recall them instantly during a design review. That is a key point: he didn’t look the numb...

Using the ADFS userinfo endpoint instead of allatclaims

In my previous post I used the allatclaims scope to get all claims in the ID token. That works, but there’s a catch: every claim you add makes the token bigger. With a lot of group memberships, the token grows quickly, and it gets sent along with every request that carries it. The alternative is to keep the ID token small and ask ADFS for the extra claims when you need them. That’s what the userinfo endpoint is for. How does it work? The userinfo endpoint is part of the OpenID Connect standard. Your application sends the access token as a bearer token, and ADFS returns the claims for that user as JSON. In ADFS the endpoint lives here: https://<adfs-server>/adfs/userinfo You can find it in the discovery document as well: https://<adfs-server>/adfs/.well-known/openid-configuration There is one important detail. ADFS treats userinfo as a resource of its own, with the identifier urn:microsoft:userinfo . The access token you send to the endpoint must be issued ...