Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
152572 stories
·
33 followers

The Emergency Stop Button - Implementing Immediate Token Revocation in .NET 10

1 Share

Imagine this sweat-inducing nightmare scenario. A banking customer's phone is stolen, and your mobile app is logged in, granting the thief complete access to their account. A frantic call comes into support. Every second counts. What is your speed-to-response for revoking that active session and securing their funds?

If you're relying on standard self-contained JWTs, the honest answer might be "up to an hour", depending on how long the token is valid. That's not going to cut it. Let's talk about how Reference Tokens give you an emergency stop button for exactly these situations, and how to wire it all up with Duende IdentityServer in .NET 10.

Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

Build .NET container images with Tekton

1 Share

Tekton is a Kubernetes-native CI/CD framework that lets you define pipelines as Kubernetes resources. If you're using Tekton to build and deploy .NET applications, the dotnet-publish-image task lets you build and push container images directly using the .NET SDK without writing a Dockerfile.

In this post, we'll walk through setting up a minimal Tekton pipeline that clones a .NET application from Git, builds a container image, and pushes it to quay.io.

How the task works

The dotnet-publish-image Tekton task uses .NET's built-in container publishing support to build and push container images. This means no Dockerfile or separate build tool is required.

The task takes a few key parameters:

  • SDK_IMAGE: The .NET SDK image to use for building (for example, registry.access.redhat.com/dotnet/sdk:10.0).
  • PROJECT: Path to the .csproj file in the source workspace.
  • IMAGE_NAME: The target image repository.
  • BASE_IMAGE (optional): The base image for the application container. When the tag is omitted, it is inferred from the project's target framework.

By default, the .NET SDK uses Microsoft's base images. To use Red Hat's .NET container images instead, set BASE_IMAGE to the appropriate image for your application type. For example, for ASP.NET Core applications use registry.access.redhat.com/dotnet/aspnet. For non-web applications use registry.access.redhat.com/dotnet/runtime.

Install the tasks

Our pipeline uses two tasks: git-clone to fetch the source code and dotnet-publish-image to build and push the container image. Install them using the Tekton CLI:

tkn hub install task git-clone
tkn hub install task dotnet-publish-image --type artifact --from redhat-tekton-tasks

Set up the image repository

We will push our example application to quay.io using a robot account. First, create a new repository at quay.io (for example, s2i-dotnetcore-ex).

Next, create a robot account and grant it Write permission on the repository.

Once that's in place, create a Kubernetes Secret with the robot account credentials. Note that the username for a robot account is your quay.io username prefixed to the robot name (e.g., myuser+myrobot):

kubectl create secret docker-registry quay-credentials \
  --docker-server=quay.io \
  --docker-username="<username>+<robot-name>" \
  --docker-password="<robot-token>"

Finally, link the secret to the pipeline service account so Tekton can provide it to all pipeline tasks:

oc secret link pipeline quay-credentials
# or: kubectl patch serviceaccount pipeline -p '{"secrets": [{"name": "quay-credentials"}]}'

Alternatively, instead of linking the secret to the ServiceAccount, you can pass the credentials directly to the dotnet-publish-image task using its optional dockerconfig workspace.

The pipeline

Here's a minimal pipeline that clones the s2i-dotnetcore-ex example application and builds a container image using Red Hat's .NET 10 SDK and ASP.NET Core runtime images:

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: dotnet-build-image
spec:
  params:
    - name: git-url
      type: string
      description: Git repository URL.
    - name: image-name
      type: string
      description: Target image repository.
  workspaces:
    - name: source
  tasks:
    - name: clone
      taskRef:
        name: git-clone
      params:
        - name: url
          value: $(params.git-url)
      workspaces:
        - name: output
          workspace: source
    - name: build-image
      runAfter:
        - clone
      taskRef:
        name: dotnet-publish-image
      params:
        - name: SDK_IMAGE
          value: registry.access.redhat.com/dotnet/sdk:10.0
        - name: PROJECT
          value: app/app.csproj
        - name: IMAGE_NAME
          value: $(params.image-name)
        - name: BASE_IMAGE
          value: registry.access.redhat.com/dotnet/aspnet
      workspaces:
        - name: source
          workspace: source

This pipeline has two tasks:

  1. clone fetches the source code from Git using the git-clone task.
  2. build-image builds and pushes the container image using dotnet-publish-image.

Run the pipeline

Create a PipelineRun to execute the pipeline:

apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: dotnet-build-image-
spec:
  pipelineRef:
    name: dotnet-build-image
  params:
    - name: git-url
      value: https://github.com/redhat-developer/s2i-dotnetcore-ex
    - name: image-name
      value: quay.io/<your-quay-username>/s2i-dotnetcore-ex
  workspaces:
    - name: source
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 1Gi

Now, start the pipeline run:

kubectl create -f pipelinerun.yaml

You can follow the progress with the Tekton CLI:

tkn pipelinerun logs --last -f

Once complete, the image will be available at quay.io/<your-quay-username>/s2i-dotnetcore-ex.

The PipelineRun uses a volumeClaimTemplate for the source workspace. Tekton automatically creates a PersistentVolumeClaim for each run and cleans it up when the PipelineRun is deleted. To control how many completed runs are retained, you can configure Tekton Pruner with history-based or time-based policies—either globally, per namespace, or scoped to specific pipelines using label selectors.

Trigger from a Git push

With Tekton Triggers, you can run this pipeline automatically whenever code is pushed to your repository. This involves three resource types that work together:

  • An EventListener exposes an HTTP endpoint that receives webhooks. It uses a TriggerBinding to extract parameters and a TriggerTemplate to create a new PipelineRun.
  • A TriggerBinding extracts values from the incoming webhook payload — for example, the repository clone URL from a GitHub push event.
  • A TriggerTemplate defines a PipelineRun template that gets instantiated with the extracted values each time an event is received.

To secure the endpoint, you can add a GitHub interceptor to the EventListener. The interceptor validates the webhook signature against a shared secret, ensuring only genuine GitHub events trigger the pipeline.

Once the EventListener is deployed, Tekton Triggers creates a Service for it. You can expose it with a Route (on OpenShift) or an Ingress, and configure it as a webhook in your GitHub repository settings — selecting the push event. After that, every push to the repository will trigger a new pipeline run that builds and pushes an updated container image.

Conclusion

The dotnet-publish-image task provides a straightforward way to build .NET container images in Tekton pipelines. It uses the .NET SDK's built-in container support, so there's no need to write or maintain Dockerfiles. Combined with Red Hat's .NET container images, this task gives you a minimal, production-ready pipeline for building and publishing .NET application images.

The task supports additional features beyond what we covered here, such as passing MSBuild properties and environment variables. For the full list of parameters and usage details, see the task documentation.

The post Build .NET container images with Tekton appeared first on Red Hat Developer.

Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

Legare Kerrison and Cedric Clyburn on LLM Performance and Evaluations

1 Share

Effectively measuring the performance of applications that are leveraging Large Language Models (LLM) is critical to the adoption of AI technologies in organizations. Legare Kerrison and Cedric Clyburn from RedHat team recently spoke at Arc of AI 2026 Conference about practical methods to evaluate and optimize LLM inference.

By Srini Penchikala
Read the whole story
alvinashcraft
24 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

How to fix NuGet vulnerabilities with GitHub Copilot in Visual Studio

1 Share

Security vulnerabilities in your dependencies are one of those things where I know that I should address them promptly, but the process of hunting down the right package version, understanding the scope of the issue, and making the change without breaking anything can turn a five-minute fix into a frustrating rabbit hole. With the Visual Studio March 2026 update, that workflow just got a whole lot smoother.

GitHub Copilot can now help you fix NuGet package vulnerabilities directly from Solution Explorer, turning what used to be a manual research task into a guided, in-editor experience.

What's new?

When Visual Studio detects a vulnerability in one of your NuGet packages, you'll now see a Fix with GitHub Copilot link alongside the vulnerability notification in Solution Explorer. One click is all it takes to kick off the process: Copilot analyzes the vulnerability, identifies the appropriate dependency updates, and implements them for you — without disrupting the rest of your project.

No more context-switching to security advisories, no more manually cross-referencing package versions, and no more second-guessing whether your fix might break something else. You stay in the editor, and the issue gets resolved right when it's discovered.

The path of least resistance

The biggest barrier to fixing vulnerabilities quickly isn't usually knowledge — it's friction. Developers know a flagged NuGet package needs attention, but when addressing it requires leaving the IDE, researching advisories, figuring out which version resolves the issue, and validating that the update is compatible with the rest of the dependency tree, it's easy for "I'll fix that later" to become the path of least resistance.

Copilot eliminates most of that friction. By surfacing the fix at the exact moment, the vulnerability is detected in the same tool you're already working in. It makes the secure choice the easy choice.

How to use it

  1. Open your project in Visual Studio 2026 Insiders (the feature is available in the latest Insiders build).
  2. In Solution Explorer, look for any NuGet package flagged with a vulnerability notification.
  3. Click the Fix with GitHub Copilot link in the notification.
  4. Copilot will analyze the vulnerability and recommend targeted dependency updates.
  5. Review the suggested changes and apply them. Copilot handles the implementation while keeping your other packages stable.

That's it. 

Security issues addressed, workflow intact. 

Happy (secure) coding!

More information

Visual Studio March Update - Build Your Own Custom Agents - Visual Studio Blog

Read the whole story
alvinashcraft
42 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

The Flaky Test Files: The Case of the State Pollution

1 Share

I once chased a bug. A very special case of a flaky test. It was a mix of a race condition and memory allocation. A real doozy.

I had a test – a bunch, really – ready to catch it when it appeared. With logs, and dumps. A wide net was cast. And you can’t build a whole test suite without thinking about the conditions of when the bug appears and when it won’t. It’s a whole model I was keeping in my head.

Then the bug reared its ugly head. And it didn’t fit the model. Tests were changed. Model replaced. The bug reappeared.

And the cycle began again. And again. I was replacing models. I was really losing my grip on reality. Or how I interpreted it.

Those tests were traps. But flaky tests have the same effect on us. We feel that our tests – which are supposed to model real use – aren’t doing their job.

But sometimes it’s much easier to fall into the rabbit hole, without race conditions. Sometimes we plant the traps we fall into.

Sometimes we don’t even notice we plant them.


Our brains are magnificent. But when we write a test, we focus on it only. We build our model of how it works, what makes it fail, and we imagine how, at the right time, we’d break down the door, shine the flashlight on the culprit and say – “stop right there.”

That mental model is built on things we know. What will happen when the test runs. How the system will behave. But really, these are just assumptions. We don’t really know.

One of the assumptions is how the system state will be when the test starts running.

Here’s an example.


In our Bigger Better Bookstore app, we have books. So if you want to check the “Create Book” feature, you’d write something like this:

def test_create_and_get_book():
    book_id = "book-123"
    book_data = {
        "unique_id": book_id,
        "title": "The Lord Of The Rings: The Fellowship Of The Ring",
        "author": "J. R. R. Tolkien",
        "price": 12.99
    }

    response = requests.post(f"{BASE_URL}/books", json=book_data)
    assert response.status_code == 201
    assert response.json()["title"] == "The Lord Of The Rings"

    response = requests.get(f"{BASE_URL}/books/{book_id}")
    assert response.status_code == 200
    assert response.json()["title"] == "The Lord Of The Rings"

Make a POST call to create it, then a GET to make sure it was created. Of course, our book IDs are unique – otherwise we won’t be able to tell all the versions of Lord of the Rings apart.

And the test passes!

If you run it once. Run it twice and it fails. The book ID is already taken. Nobody cleaned up the book created in the first run.

That’s a very simple case of State Pollution. The test changes the initial state of the system – in time for the next time.

Of course, once you understand what happened, you’ll find a fix. But what led us down the path of fragility?

The assumption that the system will always start out the same way. Maybe we thought we’d take care of the cleanup. Or someone else would. Or we didn’t think about it at all.

Which happens a lot. We can’t think of everything, all the time.


State Pollution is just one flavor of assumption. There are a lot more. Every flaky test is built on assumptions. Most of them are true most of the time. Except the ones that fail us.

The fix in this case? Clean up after yourself, or use a unique ID every run. But more importantly, how do we avoid it next time?

You need to ask yourself: when this runs again, is it starting always from the same point?

By the way, if you generate tests in bulk, the genie brings its own assumptions. Get ready for a surprise or ten.


On June 3rd, I’m running the next webinar: “Modern API Testing: Fighting Flakiness.”

We’ll go through a whole lineup of suspects — with live examples. Each one has a signature. Each one hides in a different blind spot.

I’ll talk about AI test generation and where it comes up with its own assumptions.

Plus — because I’m lazy and can’t trust myself, I built a tool. It reads my test code and tells me what was I thinking. Or implicitly assuming. I’ll show it too.

June 3rd, 3PM CET / 9AM EDT. Free.

Register Now

The API Testing Strategist Masterclass

Flakiness deserves a lot more than a webinar. A whole module in the Masterclass will teach you how to fight flakiness.

Seven weeks. Live. With me.

Twenty seats. Early bird is $599 until May 4th.

See The Masterclass

P.S. I never caught that bug. Probably moved to another app.

The post The Flaky Test Files: The Case of the State Pollution first appeared on TestinGil.
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Release v0.99.0

1 Share

Hero image of what's new in version 0.99

Installer Hashes

Description Filename sha256 hash
Per user - x64 PowerToysUserSetup-0.99.0-x64.exe 1E3586A2ECD454B86FE61C44B003E0027FCC24DCB5135958B73D04A58285618C
Per user - ARM64 PowerToysUserSetup-0.99.0-arm64.exe 2BCA2A1EDB0077FAF752DDE95C8D02A0A7A70F8E5128F43EA58432BBBE4E3C62
Machine wide - x64 PowerToysSetup-0.99.0-x64.exe 47D193F77A99FFB606A5E7132B0736BB0FB86BED6F30D68C4269DBDD6928C0AF
Machine wide - ARM64 PowerToysSetup-0.99.0-arm64.exe B9E9CDDBFE17F785A1A05420636AD716A323FC26B8D55D3B554879BB1F0BF2E8

Highlights

PowerToys 0.99 introduces Power Display for controlling your monitors from the system tray, Grab And Move for quickly moving and resizing windows, and a wave of improvements to Command Palette and the Dock, along with updates across the utility suite.


🪟 Introducing Grab And Move - Linux-style window manipulation (Preview)

This release introduces Grab And Move, a new utility that lets you drag and resize windows without having to target the title bar or window edges. Hold Alt + Left Click anywhere on a window to drag it, or Alt + Right Click to resize it from wherever your cursor is. For users who already use Alt as a system modifier, you can now choose to use the Win key instead.

GrabAndMove

Grab And Move is ideal for large monitors or windows that have moved off-screen, and it integrates with the existing Settings experience including GPO policy support, an OOBE page, and a modifier-agnostic configuration UI.

#44936 by @foxmsft



🖥️ Meet Power Display: control your monitors right from the system tray

Meet Power Display, a new utility that lets you control your hardware monitors right from the system tray. Once enabled, you can open the flyout from the tray icon or a configurable shortcut to quickly access your connected monitors. Power Display automatically detects your displays and, if supported, lets you adjust settings like volume, brightness, contrast, and color profile. No more reaching for those hard to find buttons on the back of your screen!

PowerDisplay

You can also create profiles to quickly switch between different setups with a single click. Profiles can be configured in Settings and will appear directly in the flyout for easy access.

Profiles

Lastly, Power Display profiles can now be automatically switched with Light Switch. In the Light Switch settings, you can select a profile as an action, making it easy to adjust your monitor settings based on the current light or dark theme.


⚡ Command Palette: Compact Dock, Calculator history, and reliability

This release brings a large set of fixes and improvements to Command Palette and the Dock. Alongside a wide range of performance and stability improvements, this release also introduces new capabilities, including support for plain text and image viewer content types for extensions, making it possible to display raw text and zoomable images directly in the content pane, as well as a persistent calculator history with options to save, reuse, delete, and clear entries, plus a configurable primary action and the ability to replace the query on enter.

We've also made several improvements to the Dock experience. You can now choose to keep the Dock always on top of other windows. When the Dock is positioned at the top or bottom of the screen, a new Compact mode is available, offering a more condensed layout that hides the subtitle!

Compact mode

Pinning has also been improved. When you pin a command from Command Palette, a new dialog lets you choose where it appears in the Dock and whether to show or hide the title and subtitle.

Pin

This release also fixes two separate typing-crash scenarios, hardens extension loading so one faulty extension no longer takes down the whole list, improves indexer search with filename broadening and Windows Search availability indicators, and adds Windows Terminal profile pinning with per-profile icons.

Massive thanks to @jiripolasek for the sustained Command Palette work across this release!



⌨️ Keyboard Manager improvements

In the last release, we introduced a new Keyboard Manager Editor that makes it easier to create and manage remappings. In this release, we are refining that experience further. You can now manually tweak recorded keys. After recording a remapping, each key becomes a dropdown, allowing you to adjust it or select keys that may not exist on your physical keyboard.

KBM1

We also added a new action called Disabled, which lets you quickly disable specific keys or shortcuts.

KBM2

We also fixed an important issue with multi line text replacement, significantly improving reliability in chat apps and plain text editors.



🔍 ZoomIt gets scrolling screenshots

ZoomIt also brings several enhancements to productivity and capture workflows. You can now take scrolling screenshots, making it easier to capture long pages or content that extends beyond the visible screen. We've also added text extraction directly when snipping, so you can quickly grab and reuse text without extra steps. In addition, the break timer has been improved with a new screen saver mode, helping you step away and take breaks more effectively.



🧩 Other notable changes

  • Image Resizer: The UI has been migrated from WPF to WinUI 3, bringing a more modern look and improved consistency with the rest of PowerToys.
  • Advanced Paste: Fixed auto-copy failing on Electron/Chromium apps like Teams and VS Code by releasing held modifier keys before injecting Ctrl+C.
  • Settings: Multiple UI and usability improvements across different utilities.
  • General: Streamlined default module states so new installations start with a lighter initial experience

Full release notes

Advanced Paste

  • Eliminated 13 XAML compiler warnings by switching x:Bind expressions on non-observable properties from OneWay to OneTime mode in #46726
  • Fixed auto-copy failing on Electron/Chromium apps (e.g. Teams, VS Code) by releasing held modifier keys before injecting Ctrl+C in #46486

Always On Top

  • Fixed the pin/unpin sound playing even when the operation failed by gating sound playback on whether SetWindowPos actually succeeded in #46910

Command Palette

Dock

  • Added a new pin-to-Dock dialog that gives users more control over how commands are pinned, replacing the previous one-click pin behavior in #46436. Thanks @niels9001!
  • Added a Compact Dock mode (28px tall, subtitle hidden) for Top/Bottom dock positions, and hid the Dock Size setting for Left/Right positions in #46699
  • Made the Dock window stay on top of all other windows by default, automatically yielding when a full-screen app is detected in #46163. Thanks @jiripolasek!
  • Decoupled the Dock context menu from the Command Bar's active item so it no longer updates when a different list item is selected, and made the Dock search box position follow the Dock position in #46420. Thanks @jiripolasek!
  • Fixed duplicate dock bands caused by missing duplicate check when pinning in #46438
  • Fixed a build-breaking merge inconsistency in DockWindow.xaml.cs in #46639. Thanks @jiripolasek!
  • Fixed the Dock not reflecting pin/unpin changes until restart in #47169
  • Fixed the Dock window showing a visible frame on startup by hiding the DWM border during window creation in #47187

Extensions & SDK

  • Added plain text viewer and image viewer IContent types to the extension SDK in #43964. Thanks @jiripolasek!
  • Added persistent calculator history with save, reuse, delete, and clear actions, configurable primary action, and replace-query-on-enter behavior in #45307. Thanks @jiripolasek!
  • Added a NetworkSpeedUnit choice setting to the Performance Monitor extension (bits/s, decimal bytes/s, IEC binary bytes/s) in #46320. Thanks @niels9001!
  • Enabled dock pinning of Windows Terminal profiles with per-profile icons, and hardened GUID parsing so a malformed profile entry no longer breaks the whole list in #46372
  • Assigned stable IDs to FancyZones layout commands in the PowerToys extension so users can pin individual layouts to the dock in #46198. Thanks @vanzue!
  • Hardened the Performance Monitor extension with exception handling and crash recovery via a sentinel file mechanism in #46541. Thanks @jiripolasek!
  • Gave each built-in extension its own settings file with transparent one-time migration from the legacy shared settings.json in #46685. Thanks @michaeljolley!
  • Shipped Copilot instructions and 5 skills (publish-extension, add-adaptive-card-form, add-extension-settings, add-dock-band, add-fallback-commands) inside the extension template in #46683. Thanks @niels9001!
  • Fixed invisible/corrupted icons in newly created extensions by extracting template expansion into a dedicated service that no longer rewrites binary files in #46490. Thanks @jiripolasek!
  • Fixed a Watson crash where a single extension in a bad state would kill the entire extension-loading loop in #47032
  • Fixed right-click context menus failing to open on the first attempt for slow out-of-process third-party extensions in #46626. Thanks @jiripolasek!
  • Fixed the Settings toggle for disabling fallback commands from out-of-process extensions by switching the type check from a concrete class to the WinRT interface in #47127
  • Simplified the Time & Date extension page to recalculate results on every query rather than caching, breaking a potential infinite update loop in #46396. Thanks @jiripolasek!
  • Fixed Calculator extension unit tests failing under non-English cultures in #46911. Thanks @niels9001!

Search & Indexer

  • Improved indexer search with implicit filename broadening for plain free-text queries, retry-with-literal matching for punctuation-heavy searches, and a Windows Search availability indicator in #46907. Thanks @jiripolasek!
  • Fixed a crash when converting large calculator results to hex/oct/bin by switching the secondary-results base conversion to BigInteger with a custom base converter in #46176. Thanks @jiripolasek!
  • Split the full-screen shortcut guard into separate full-screen and busy checks with an opt-in IgnoreShortcutWhenBusy setting, added a live diagnostic InfoBar, and introduced an opt-in triple-press breakthrough to bypass suppression in #45891. Thanks @jiripolasek!
  • Fixed the Window Walker Close window command to respect the "Keep open after closing window" setting and automatically refreshed the window list in #45721. Thanks @jiripolasek!

Reliability & UX

  • Fixed a 100% reproducible crash when typing in the search box by adding a reentrancy guard around filtered-items mutations in #47148. Thanks @MuyuanMS!
  • Fixed a second typing crash that occurred when the indexer fallback was enabled by correcting a P/Invoke function signature in #47186
  • Hardened ListViewModel item-fetch synchronization with copy-on-write cache publication, latest-fetch-wins semantics, and improved cancellation cleanup in #46429. Thanks @jiripolasek!
  • Refactored settings and app state to be immutable end-to-end to eliminate concurrency race conditions in #46451. Thanks @michaeljolley!
  • Added a CanGoBack guard to Frame.GoBack, preventing a crash when navigating back with an empty navigation stack in #46493. Thanks @jiripolasek!
  • Fixed duplicate and contradictory Pin to Dock/Unpin from dock context menu entries appearing on top-level home-page items in #46458. Thanks @michaeljolley!
  • Prevented PgUp/PgDown paging from landing on non-interactive entries like separators and section headers in #46439. Thanks @jiripolasek!
  • Fixed keyboard focus restoration on the Extensions settings page so Shift+Tab returns to the previously selected extension card in #45903. Thanks @jiripolasek!
  • Reverted focus-restoration on the Extensions settings page that was causing clicks to open the wrong extension item in #46642. Thanks @jiripolasek!
  • Fixed inline code (backtick text) in the Details and Content panels being invisible on light-theme backgrounds in #46739. Thanks @michaeljolley!
  • Fixed the Window Walker "Not Responding" tag being illegible in dark mode in #46924. Thanks @niels9001!
  • Fixed a WinUI layout bug where the settings page content was visually offset when wrapped in a ScrollViewer with MaxWidth in #46568
  • Fixed a regression in PinToDockDialogContent.xaml where a type rename was missed during a merge gap in #46599. Thanks @jiripolasek!
  • Fixed a screen reader accessibility issue where the Alias text box announced "Enter Alias" instead of just "Alias" in #45906
  • Added screen reader announcements for shortcut key information on the settings button in #46164. Thanks @chatasweetie and @jiripolasek!
  • Removed redundant container-level tab stops in the details panel for improved keyboard accessibility in #46346. Thanks @chatasweetie!

Infrastructure & Code Quality

  • Extracted persistence and file I/O logic from SettingsModel and AppStateModel into dedicated service classes in #46312. Thanks @michaeljolley!
  • Introduced CmdPalLogger, CmdPalLoggerProvider, and an extension method integrating Microsoft.Extensions.Logging with ManagedCommon.Logger in #46768. Thanks @michaeljolley!
  • Bumped all CommunityToolkit.WinUI packages from 8.2.250402 to 8.2.251219 and removed three SearchBar workaround hacks in #46027. Thanks @niels9001!
  • Enabled telemetry event firing correctly in AOT builds by adding EventSourceSupport in #47121
  • Updated the extension solution filter files to include new transitive dependencies and added a leaner SLNF for faster developer builds in #46896. Thanks @jiripolasek!
  • Updated the Microsoft.CmdPal.Ext.PowerToys solution filter file to include missing project dependencies in #46136. Thanks @jiripolasek and @vanzue!
  • Removed a legacy workaround for FontIconSource.CreateIconElement (fixed in WinAppSDK 1.8.4) in #45790. Thanks @jiripolasek!
  • Moved developer documentation to doc/devdocs/modules/cmdpal to align with other PowerToys modules in #46926. Thanks @niels9001!
  • Bumped Command Palette version to 0.10 in #47181

Image Resizer

  • Migrated Image Resizer from WPF to WinUI 3, unblocking future AOT compilation and aligning with Windows 11 design language in #45288. Thanks @moooyo and @niels9001!
  • Restored honoring the user-configured JPEG quality setting when resizing JPEGs, which had been silently ignored at a fixed ~Q90 default after the WinUI 3 migration in #47134
  • Fixed missing PNG encoder settings by applying codec-specific encoder properties in the transcode path in #46695. Thanks @moooyo!
  • Fixed a regression where JsonPropertyName attributes were not forwarded by the ObservableProperty generator, restoring correct JSON serialization in #47056

Keyboard Manager

  • Reverted multiline text replacement back to character-by-character sending with Shift+Enter for newlines, fixing multiline replacements in chat apps and plain editors in #46794
  • Addressed code review feedback on manual key selection: fixed localization, centralized VK_DISABLED constants, added validation for disable mappings, fixed dropdown revert logic, and plugged Process handle leaks in #46377

Light Switch

  • Fixed Light Switch and PowerDisplay integration by re-enabling the Apply monitor settings expander and disabled-warning InfoBar in Settings, and ensuring every hotkey press notifies PowerDisplay instead of only every other press in #47190

Mouse Utilities

  • Refactored PadImage in PowerOCR (Text Extractor) to improve memory management and nullability clarity in #44906. Thanks @adelobosko!

Peek

  • Added auto-detection of file name encoding when previewing zip files, fixing garbled text for archives created on non-UTF-8 systems in #44799. Thanks @oxygen-dioxide!

Power Display

  • Re-enabled the PowerDisplay module with a new icon/logo, DPI fixes, UI/UX improvements, and installer integration in #46489
  • Cleaned up the PowerDisplay module by fixing resource leaks, removing dead code, converting a recursive parser to iterative, and changing the default activation shortcut to Win+Ctrl+Shift+P in #46979
  • Fixed thread safety by marking shared fields as volatile, guarding color temperature writes behind a capability check, and correcting a misleading log message in #47008
  • Fixed PowerDisplay startup restore, volume initialization, and Identify window lifecycle in #47051
  • Introduced a shared flyout positioning helper used by PowerDisplay and Quick Access, fixing taskbar overlap at 100% scaling and off-screen rendering after DPI changes in #47097
  • Polished Power Display by standardizing the module name, shrinking the flyout slightly, and removing dead code in #47163

PowerToys Run

  • Fixed a command breakout in the Shell plugin by escaping double quotes in the command string, while still allowing environment variables to expand in #45554. Thanks @RinZ27!
  • Removed unused XAML namespace declarations from PowerLauncher XAML files in #46221. Thanks @niels9001!

Quick Accent

  • Added subscript and superscript Unicode characters to the Special Characters set for keys 0-9, A, E, N, X, Y, Z, and math operators in #45540. Thanks @Salehnaz!
  • Added the missing Icelandic accented letter í to the VK_I key definition in #46424. Thanks @squirrelslair!
  • Added Shift+N capitalization support for superscript Latin small letter n in #46571. Thanks @PesBandi!
  • Restored the en-dash character under the VK_MINUS key in the Special Characters set in #47106
  • Fixed the default "All available" language setting silently falling back to a small character set due to parsing issues, added case-insensitive parsing with invalid-entry warnings, and added two new Hungarian character mappings in #47117. Thanks @daverayment!

Settings

  • Fixed the Settings shortcut/key visuals so arrow glyphs (up/down/left/right) render as proper FontIcon glyphs instead of literal text in #46454. Thanks @vanzue!
  • Formatted the last checked for updates timestamp as friendly relative strings (Today at 1:22 PM, Yesterday at 3:45 PM) in #46923
  • Fixed Dashboard layout issues by removing excessive empty scroll space, restoring responsive behavior, and correcting a 1-pixel vertical alignment mismatch in #46922
  • Fixed the Quick Accent character-sets grid being clipped and showing an inner horizontal scrollbar, so the list reflows from 3 to 2 to 1 columns on resize in #45986. Thanks @daverayment!
  • Renamed the shortcut conflict checkbox label from "Ignore shortcut" to "Ignore conflict" for clarity in #46318
  • Fixed the backup folder path being visually clipped on the General and Image Resizer pages in #46920
  • Refreshed Settings UI assets and copy: fixed a ZoomIt page regression, updated the Command Palette settings page with current links and screenshots, and added missing overview screenshots in #47132
  • Fixed missing images in the Settings UI by adjusting the project file so image assets are packaged correctly in #47165
  • Tweaked wording on a handful of Settings strings for clarity and consistency in #47164

Text Extractor

  • Removed the third-party WPF-UI library in favor of native WPF Fluent theming with custom control templates in #46218

Window Manager (Grab And Move)

  • Added the Grab And Move module enabling Alt+Left Click window dragging and Alt+Right Click window resizing, without needing to target title bars in #47024
  • Unstuck the Alt key after Ctrl+Alt+Del or Alt+Tab into an admin process, made Win selectable as the move/resize activation modifier, and made the window geometry readout opaque in #47052. Thanks @foxmsft!
  • Updated Grab And Move Settings strings to be modifier-agnostic now that Win is selectable alongside Alt in #47178

ZoomIt

  • Added panoramic/scrolling screenshot capture, text extraction when snipping, and break timer improvements with screen saver mode and optional computer lock in #46506. Thanks @foxmsft, @MarioHewardt, and @markrussinovich!
  • Fixed ZoomIt x86 build compatibility by emulating the _mm_cvtsi128_si64 intrinsic with _mm_storel_epi64 for 32-bit targets in #46529. Thanks @foxmsft!

Development

  • Added a full OOBE page for Grab And Move, high-resolution icons and overview images for both Grab And Move and PowerDisplay, NEW badges on Settings nav items, and refreshed the README utilities table in #47033
  • Added an update-available badged tray icon, a new "Update available" tray menu entry that opens Settings to General, and raised the update InfoBar severity to Warning in #47030
  • Updated the dark-mode PowerToys tray icons to use the correct shade of black for the outline in #47166
  • Changed default-on state for new installations by disabling 7 modules by default to streamline the initial experience for new users in #47027
  • Added explicit default-disabled overrides to eight module interfaces so the native Runner defaults match the managed enabled-modules list, eliminating first-launch enable/disable flicker in #47144
  • Updated the Windows Implementation Library (WIL) from 1.0.231216.1 to 1.0.250325.1 via Central Package Management in #43503
  • Fixed the build.ps1 script so the -RestoreOnly switch works correctly and added support for the newer .slnf solution filter file format in #46012. Thanks @raycheung!
  • Upgraded the check-spelling CI action to v0.0.26 which fixes spell-check failures on fork PRs and updates exclusion patterns in #46851. Thanks @jsoref!
  • Refreshed the check-spelling action to 0.0.26 and synced dictionaries, patterns, and expect/reject lists across docs, source, and resource files in #47119. Thanks @jsoref!
  • Pinned the check-spelling GitHub Action to v0.0.26 to attempt to fix the CI pipeline blocking PRs from forked repositories in #46746
  • Reverted the pinning of the check-spelling action after determining that the pin was unrelated to the pipeline issue in #46749. Thanks @moooyo!
  • Added contributor names from a recent PR to the spellchecker allow-list to prevent CI spelling errors in #46765. Thanks @jiripolasek!
  • Added comprehensive DSC (Desired State Configuration) documentation with per-module reference pages, settings examples, and an overview guide covering 25+ PowerToys modules in #42554. Thanks @Gijsreyn!
  • Cleaned up root-folder Markdown files by consolidating bullet styles, fixing spelling and grammar, converting HTML to Markdown, and applying sentence-case headers in #46582. Thanks @Jay-o-Way!
  • Documented three missing telemetry events (ModuleLaunchedFromSettings, CmdPal_DockConfiguration, KeyboardManager_LaunchEditor) in #46371
  • Added telemetry event logging to CLI entry points for FileLocksmith, Awake, and Image Resizer so command-line invocations are tracked alongside GUI usage in #46872. Thanks @MuyuanMS!
  • Added 75+ MSTest unit tests covering Hosts ValidationHelper (IPv4/IPv6/hostname validation) and ColorPicker ColorFormatHelper conversions (CMYK, HSB/HSI/HWB, CIE XYZ/LAB, Oklab/Oklch, sRGB-linear, NCol) in #46679
  • Fixed MSTEST0017 analyzer warnings by correcting assertion argument order in 22 Assert calls across 8 test files in #46712
  • Fixed a CI test hang where Common.Interop.UnitTests.TestSend could block for 80 minutes when a prior run left a named-pipe handle alive, by ensuring pipe names are unique per run and bounding handshake waits in #47123
  • Resolved StyleCop SA1614, SA1616, SA1622, and SA1623 warnings across Command Palette, Power Display, Settings UI, DSC, and Extensions Toolkit code in #46706, #46707, #46717, #46718
  • Bumped the azure/login GitHub Action from v2 to v3 in the MS Store submissions workflow in #46323
  • Bumped the azure/cli GitHub Action from v2 to v3 in the MS Store submissions workflow in #46562
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories