Category Archives: PowerShell

Removing Stubborn Acrobat Pin

I keep learning more and more about hidden wrinkles in WinGet. I guess that’s because I use it every day, and notice when things get hinky. Today, I noticed my pin on Adobe Acrobat got stuck like Schrodinger’s cat: it was there and not-there at the same time. Ultimately, this had me removing stubborn Acrobat pin, as normal methods couldn’t do their job. Let me explain…

What’s Involved When Removing Stubborn Acrobat Pin?

Take a look at the WinTerm screen capture that starts off this blog post. After running winget upgrade ... I got a message “1 package(s) have pins that prevent upgrade.” Flo6 has 2 pins right now and one of them has no internal version number (GNU Backgammon) so I knew the affected package must be Adobe Acrobat. You can see both packages as output to the winget pin list, in fact.

But as you can see in the next two lines, neither winget list --id... nor winget pin remove recognized Adobe.Acrobat.Reader.64-bit as a valid package name. That’s decidedly odd, because that’s the name that shows up in winget pin listoutput shown earlier.

Turns out that’s a thing. It’s a short form versus long, explicit form discrepancy.

Why the Short Form Fails

When you run winget pin remove without explicit flags, winget uses positional argument matching. It tries to match the string Adobe.Acrobat.Reader.64-bit against its installed packages database first. It does not go straight to the pin store.

If WinGet cannot find a recognized installed package entry for that string, it stops. It bails out before it ever reaches the pin database. The pin record sits untouched.

This mismatch happens for a specific reason. Adobe Acrobat was likely removed through Windows Settings or Add/Remove Programs, not through winget uninstall. Winget never got the chance to clean up its own records. So the installed-package record disappeared, but the pin record survived in winget’s separate pinning.db database file.

That gap between the two databases is the root cause of the error. The fix is to route Winget around that gap entirely.

The Fix: Explicit Flags

The solution is to be explicit with WinGet. To do that, add two flags to the command: –id and –source. Together, they change how winget searches. Use this exact command:

winget pin remove --id Adobe.Acrobat.Reader.64-bit --source winget

Here’s how this works: The --id flag forces WinGet to look up the package by its exact manifest identifier. The --source flag tells WinGet to look specifically in the winget source. Together, they bypass the installed-package correlation step and go straight to the pin store.

The output confirms it works. You see “Found Adobe Acrobat Reader (64-bit) [Adobe.Acrobat.Reader.64-bit]” followed immediately by “Pin removed successfully.” Run winget pin list one more time to confirm the pin is gone. It will be.

This is the cleanest way to use winget pin remove whenever a package no longer has a matching installed record. Keep those flags in your back pocket.

Take the Long Way Home

When winget pin remove fails with “No installed package found,” the short form is matching against the wrong database. Adding
--id and --source redirects it straight to the pin store, where it needs to go. Always uninstall packages through WinGet when you can. That keeps its databases in sync and prevents this mismatch from happening in the first place. A little discipline now saves a lot of troubleshooting later, and now you know exactly what to do when things go sideways despite your best efforts. A not unfamiliar sensation to those who, like me, run in the halls of Windows-World.

Facebooklinkedin
Facebooklinkedin

WinGet Mistakenly Reports Discord as Pinned

Here’s a scenario many Windows users will recognize. You open a terminal and run winget upgrade to freshen up your apps. Everything looks normal — until you spot Discord sitting there labeled “pinned.” You never pinned it. You have no idea why it shows up that way. Sound familiar? Turns out that WinGet mistakenly reports Discord as Pinned for its own, somewhat murky reasons.

This WinGet Discord pinned situation surprises a lot of people. It looks wrong, or like WinGet won’t update a much-used app. Neither is true.

Take a breath. Discord is fine. WinGet is fine. There’s a perfectly logical explanation — and once you see it, the whole thing makes complete sense. Let me fill  you in…

Why WinGet Mistakenly Reports Discord as Pinned

WinGet uses the “pinned” label for two very different situations, and it doesn’t distinguish between them visually. The first situation is one you control: you run winget pin on a package, and WinGet holds that app at its current version. That’s an intentional, user-driven pin.

The second situation involves the app’s own manifest. Package maintainers can set a field called RequireExplicitUpgrade to true inside their installer’s YAML file. When WinGet sees that flag, it skips the package during bulk upgrade runs. Then, it labels it as “pinned” in the output.

Discord’s manifest resides in the winget-pkgs repository. ICYDK, that’s the Microsoft community Windows Package Manager manifest repository on GitHub. There, its manifest carries RequireExplicitUpgrade: true across many versions, including 1.0.9005, 1.0.9166, and 1.0.9188. WinGet groups both user-set pins and manifest-driven flags under the same display label. That shared label is the root of all this kerfluffle.

Why Discord Sets RequireExplicitUpgrade

Discord ships with its own built-in auto-updater. Most of the time, Discord updates itself quietly in the background without you lifting a finger. It doesn’t need WinGet’s help to stay current. It runs by default each time you open the app (or restart your PC).

Setting RequireExplicitUpgrade: true in the manifest tells WinGet to stand down during bulk winget upgrade runs. This prevents WinGet from downloading and launching a full installer that could interfere with Discord’s own update mechanism. Two updaters competing for the same app can be a recipe for trouble.

This is actually a smart, deliberate design choice. Thus, it’s not a bug, nor an oversight. The Discord team and the winget-pkgs maintainers made a deliberate call to keep things tidy. WinGet and Discord each do their own job, without stepping on each other.

How to Check the Discord Manifest

Want to see Discord’s package details for yourself? Start with this command:

winget show --id Discord.Discord

This output gives you useful metadata — the current version, publisher, installer URL, SHA256 hash, and release date. What it does not show is the RequireExplicitUpgrade field. winget show surfaces display metadata, not every field in its YAML manifest.

The file Discord.Discord.installer.yaml does not exist on your local PC. It lives only on GitHub. To find it, go directly to this URL in your browser. (Swap in whatever the current version number is for 1.0.9258 if needed.) Once there, look for RequireExplicitUpgrade: true in the YAML. That single line is what tells WinGet to treat Discord as a skip-by-default package during bulk upgrades. You can see it highlighted in the lead-in graphic at line 16 of that YAML file, in fact.

Upgrading Discord Through WinGet Anyway

Maybe you want WinGet to handle the Discord update on your terms. No problem. You can override the RequireExplicitUpgrade flag with a single targeted command:

winget upgrade --id Discord.Discord --force

This tells WinGet to update Discord explicitly, bypassing the manifest flag just for this one run. It’s a clean, safe way to push a WinGet-managed update when you want one.

That said, most of the time you won’t need to bother. Discord’s own updater does its job reliably and quietly. The WinGet Discord pinned label looks alarming, but your Discord client is almost certainly already up to date. Check the app’s version in its settings if you want confirmation.

WinGet Category Conflation Explains All

The “pinned” label WinGet shows for Discord is not a real user-set pin. Again, you did nothing wrong, and nothing is broken. It reflects the RequireExplicitUpgrade: true field baked into Discord’s own manifest That tells WinGet to step aside and let Discord’s built-in updater do its thing. Once you understand the distinction, WinGet’s behavior makes perfect sense. This behavior is simply misreported as “pinned” not “RequireExplicitUpgrade.”

Now that you know what’s going on, you can look at that “pinned” label and nod knowingly instead of scratching your head. That’s what understanding tools is all about. That makes you a sharper and better-informed inhabitant, here in Windows-World.

Facebooklinkedin
Facebooklinkedin

Strange DirectX Pin on Flo6

I was doing a routine check of my WinGet pin list on Flo6 just now (ICYMI, Flo6 is my production desktop). After running winget pin list I spotted three pinned packages. Two of them I recognized immediately. Adobe Acrobat Reader (64-bit) and GNU Backgammon  I pinned myself, on purpose. But the third one stopped me cold. It showed Microsoft.DirectX at version 9.29.1974.0. I had never pinned that. Why did I see this strange DirectX pin?

How I Got a Strange DirectX Pin on Flo6…

First, let me share some background. Modern DirectX, meaning DirectX 11 and DirectX 12, is baked directly into Windows. Windows Update manages it entirely. Winget does not install, update, or remove it. How, then, did it make its appearance?

The Microsoft.DirectX package from the WinGet community catalog is something else entirely. It refers to the DirectX End-User Runtime redistributable, specifically its June 2010 release. That’s the last one MS ever shipped.

Indeed, Version 9.29.1974.0 is the final, frozen-forever build. It’s unchanged since 2010. Back in the day, games and apps from that era bundled this runtime to pull in legacy components. Think D3DX9, XAudio2, and XInput. On most modern Windows systems, this redistributable is obsolete and irrelevant.

The Source of This Strange Pin May Be…

Here’s where things get weird. The Microsoft.DirectX manifest in the WinGet community catalog had a long-running typo. For a while, it listed the package version as 9.29.1974.1 instead of the correct 9.29.1974.0. A community contributor eventually caught the error and submitted a pull request to fix it.

Once that fix merged into the catalog, WinGet suddenly saw a mismatch on affected machines. The catalog now declared 9.29.1974.0 as current. The installed runtime also reported 9.29.1974.0. So far so good. But the metadata around the install technology did not reconcile cleanly. Windows owns and controls the DirectX runtime. WinGet does not.

Winget could neither upgrade the package nor cleanly resolve the discrepancy. So it did the next best thing. It quietly added a Pinning-type pin to suppress its spurious upgrade prompt. That kept its noise out of winget upgrade --all output. In short, winget added the pin to stop nagging itself about a package it cannot actually manage. I have to laugh about that, give me a moment…

Removing the DirectX Winget Pin Is Safe

The good news here is straightforward. This pin is purely administrative. WinGet created it as a workaround for its own catalog inconsistency. It was never protecting anything vital.

Removing the pin leaves the DirectX runtime alone. The actual runtime stays right where it is. Windows Update continues to manage it, same as always. Better yet, the phantom upgrade version, 9.29.1974.1, is already gone from the WinGet catalog. Removing the pin won’t spur any bogus upgrade attempts. Nothing bad is waiting to happen.

The command to remove it is simple:

winget pin remove --id Microsoft.DirectX --source winget

As you can see in the screenshot above, the operation returns “Pin removed successfully” in under two seconds. A quick follow-up winget pin list confirms the DirectX entry is gone. No drama, no side effects.

Separating Signal from Noise

This episode is a good illustration that WinGet isn’t infallible. Sometimes its catalog or tooling leaves artifacts behind that look alarming but turn out to be harmless. The DirectX pin on Flo6 was exactly that: a breadcrumb left by WinGet’s own error-handling logic, not by anything I did. A single one-liner clears it up in seconds. Now, winget pin list shows only packages I actually chose to pin. That is exactly how it should be, and I am glad to have one less mystery on my machine. That counts as a win, here in Windows-World. Cheers!

Facebooklinkedin
Facebooklinkedin

In-app Update Beats Remove/Replace

Running WinGet just now on my Flo6 desktop, I got reminded that installer changes sometimes stymie its update facilities. If you look at the lead-in graphic, you’ll see that one upgrade gets blocked because of “different install technology.” Winget goes onto recommend “Uninstall each package, then install the newer version.” Not so fast: IMO, an in-app update beats remove/replace when that’s an option. I’ll explain, and use the Edge browser as an illustration.

You can jump to Edge, click the ellipsis, and get to Help and feedback in 3 clicks. Uninstall/reinstall takes 20+ keystrokes, and might fail.

Why Say: In-app Update Beats Remove/Replace?

My explanation boils down to: less time and effort, fewer keystrokes involved. Jumping to Edge, clicking the ellipsis for Settings, then visiting Help and Feedback to prompt the update process takes 3 mouse clicks (add one more click to restart, and the update is done). Uninstalling, then re-installing edge takes at least 20 keystrokes (“winget uninstall edge”). Worse, it then falls victim to exit code 93. TLDR version: Edge is considered a Windows built-in feature, so it blocks its own uninstall by default.

Sure, you can work around this. And it works for other browsers as directed for Chrome, Firefox, and so forth. But my preferred approach for browsers in particular is: try the built-in update mechanism first, if WinGet steers around an update. It usually does so for a good reason, as is the case here with Edge.

Here in Windows-World, it pays to recognize such cul-de-sacs when they pop up. It saves you the time involved in driving to the end, turning around, and doing something else. Not an unfamiliar experience for Windows warriors, but one best avoided when possible!

Facebooklinkedin
Facebooklinkedin

Fixing False Vantage Update

If you’ve ever dealt with a Lenovo Vantage false update, you know how maddening it gets. That goes double, when every install attempt fails silently and the same ghost package reappears on every subsequent scan. Sigh.

But that’s precisely what happened to me on a Lenovo ThinkStation P3 Ultra Gen 2 (Arrow Lake-S desktop). There, Lenovo Vantage’s System Update panel stubbornly flagged Intel Dynamic Tuning Technology (DTT) Driver version 9.1.10001.173 as a required update, even after reporting a successful install on the previous try. Sigh again.

Why I’m Fixing False Vantage Update

Here’s the wrinkle: DTT is a laptop-exclusive power-management feature. It’s tightly coupled to Intel’s thermal sensor bus. Specifically, it applies to SWC\VID8086_DTT_* ACPI devices. Alas desktop platforms don’t sport them. My ThinkStation doesn’t have one. It never will. Yet Vantage keeps insisting otherwise.

Furthermore, every install attempt failed without so much as an error dialog. Vantage just re-offered the driver on the very next scan, politely pretending nothing had gone wrong. Time to dig in, and get this thing outtah heah!

Ruling Out the Obvious

First, I tried some obvious remedies. Logging into Vantage directly as Administrator changed nothing. There’s no ellipsis menu, no right-click context option. That means no “suppress this update” checkbox anywhere in the System Update panel. Lenovo simply hasn’t built that in.

Next, I turned to the standalone Lenovo System Update app. After installing the optional Lenovo SoftwareComponent Driver 26.9.0.20 from Windows Update, System Update scanned the machine and correctly reported “No packages applicable.” Clean bill of health. Meanwhile, Vantage still flagged the DTT driver for update. Sigh one more time.

However, that discrepancy was actually useful. It proved the issue lived entirely inside Vantage itself. It’s an artifact of its System Update addin, not  Lenovo’s underlying package catalog. The two tools evaluate the same catalog through completely different pipelines. Importantly, only one of them is wrong.

Tracing That False Positive…

With the obvious paths ruled out, I dug into Vantage’s session data folder:
C:\ProgramData\Lenovo\Vantage\AddinData\
LenovoSystemUpdateAddin\session\
.

Inside, I found two SQLite databases: update_history.db (Vantage’s live working store, rewritten on every scan) and editable_update_history.db (which appears designed to accept external edits). I tried setting the DTT entry status to NotApplicable in the editable_update_history.db. Alas, nothing changed on screen. Vantage reads update_history.db for all rendering decisions and overwrites it with Applicable again after each rescan. The “editable” database, it turns out, is a red herring.

I also found available_updates.json.It’s a 5 KB file that’s rewritten upon each update scan. It gave me a fully parsed package definition, including a Dependencies block that pointed me toward the real culprit.

A (Bogus) WildCard in the XML

Vantage caches each package’s raw XML in its own repository subfolder. For this machine, the DTT package XML lives at:

session\Repository\m1dpf015d_p3ultrag2_25h2\m1dpf015d_p3ultrag2_25h2_2_.xml

Inside that XML, the Dependencies/_Bios/Level section contained two machine-type entries: “*” and “S0NKT*”. The S0NKT* pattern correctly targets specific Lenovo laptop lines that carry DTT-capable thermal silicon. That entry belongs there. The “*” wildcard, however, matches every machine type on the planet — including the ThinkStation’s 30J5 machine type. That entry almost certainly doesn’t belong there, and it looks like a straightforward Lenovo catalog error.

Consequently, without the wildcard, Vantage evaluates the ThinkStation’s machine type against S0NKT*, finds no match, and writes NotApplicable to update_history.db automatically on every future scan. No database patching, no registry hacks — just the correct answer from a corrected applicability list.

PowerShell to the Rescue!

I wrapped the repair into a short PowerShell script called fix_dt.ps1. The logic is straightforward: clear the file’s read-only attribute, load the XML into an XmlDocument object, locate the offending node using an XPath query, remove it, save the file, restore read-only protection, then restart the LenovoVantageService so Vantage picks up the change cleanly.

The lines that do the heavy lifting are (edit to remove line breaks):

$node = $v.SelectSingleNode("//_Bios/Level[. = '*']")
if ($node)
{ $node.ParentNode.RemoveChild($node) | Out-Null }

Setting the file back to read-only afterward is an important step. It prevents Vantage from silently re-downloading a fresh copy of the XML on its next catalog sync and re-introducing the wildcard. Sadly, that would undo the fix entirely.

To run the script, open an elevated PowerShell prompt and execute:

powershell -ExecutionPolicy Bypass -File
"C:\Temp\fix_dt.ps1"

Note: Run this from an elevated (Run as Administrator) PowerShell session. The script must stop and restart the LenovoVantageService, which requires administrator rights. Edit so it runs on one line.

Lessons Learned

This exercise surfaced a few things worth minfing for anyone who’s doing deep Vantage troubleshooting:

  • Vantage and the standalone System Update utility maintain completely separate state databases and catalog evaluation pipelines. Agreement between them is not guaranteed. Disagreement is a useful diagnostic clue, not a dead end.
  • The “editable” SQLite database is a red herring for display suppression. Vantage ignores it when rendering the System Update panel. Don’t waste time on this.
  • A single bogus wildcard in a machine-type applicability list causes a laptop-only driver to haunt a desktop indefinitely. The fix is in the XML, not in the database.
  • When the official UI offers no suppress or hide option for a persistently wrong update, the XML repository is the right lever to pull. Appearances aside, it’s not the SQLite layer above it at fault.

Ultimately, this is a reminder that catalog quality control matters. One stray “*” in a dependency block can send thousands of ThinkStation owners chasing a ghost driver that will never install. If you’ve hit the same Lenovo Vantage false update on a different ThinkStation model, or if you’ve spotted a similar wildcard problem in another Vantage package XML, please drop a comment here. I’d love to know how broadly this catalog bug extends beyond the P3 Ultra Gen 2.

Here in Windows-World, updates sometimes get weird. This time, for once in a blue moon, it’s not WU that’s the culprit. It’s Lenovo. That makes me oddly glad. Go figure!

Facebooklinkedin
Facebooklinkedin

WinGet.Config Drives Developer Config

As I was reading a Windows Latest article about a “…special Windows 11 for power users…” this morning, I found myself wondering. “Could this be a big, fancy WinGet config file at work?” Indeed, reading further into the story absolutely confirmed my hunch. The file in question, in fact, is named winget.config, in keeping with current naming conventions around desired configuration states. Thus, it’s simple truth that Winget.Config drives “Developer Config” as described in the story (and at MS Learn as well).

WinGet.Config Drives Developer Config from End to End

The MS Learn article‘s intro paragraph is worth quoting in full to put this capability into clear context:

Windows Developer Configurations are a curated, open-source collection of configuration files that take a fresh Windows machine to a ready-to-code state with a single command. Each config is a declarative file that is safe to re-run. It describes the packages, OS settings, and post-install steps for a specific scenario (a full developer workstation, a comfortable WSL shell, or a single language toolchain), so you can rebuild your environment on any machine without clicking through installers or maintaining custom scripts.

Windows Developer Config is built from the ground up on winget configure and a single .winget desired state configuration (DSC) file named dev-config.winget. It is not a new Windows SKU, a custom ISO, nor a registry script. The whole thing is one winget configure call pointing at that file.

The commands necessary to instill this configuration are (mostly) shown in the lead-in graphic. I repeat them here for completeness’ sake (and for easy cut’n’paste, by copying non-comment lines completely):


# Enable WinGet Configuration first
winget configure --enable

# Clone the repo
git clone https://github.com/microsoft/WindowsDeveloperConfig.git
cd WindowsDeveloperConfig

# Apply the config
winget configure -f .\windows-dev-config\dev-config.winget –accept-configuration-agreements –disable-interactivity

More About WinGet.Config

That .winget file is a YAML-based DSC manifest that handles everything in one shot: installing PowerShell 7, Git, GitHub CLI, VS Code, .NET SDK, Python, Node.js, PowerToys, setting up WSL with Ubuntu, tweaking Windows Terminal defaults, enabling Developer Mode and long-path support, and applying a long list of Explorer/Start/Search/Widgets settings to declutter the UI.

Indeed, Project Zenith hardware ships with those same changes baked-in by the OEM. But the underlying mechanism Microsoft used to define and apply that configuration is exactly the same winget configure + .winget file approach. In fact, the .winget config file format is doing real work here. That is, it’s not just installing apps; it’s functioning as full-blown Windows DSC, a notable expansion beyond what most people think winget does.

Here in Windows-World, it’s great to see real innovation put to useful work. Demitrius Nelon, the head of the WinGet team, has told me several times over the past few months that .winget configuration files represent a way to customize Windows seriously in one go. Now, I think I understand what he was getting at. Great work, guys!

Facebooklinkedin
Facebooklinkedin

Long DISM Pause at 63% Range

I’ve been reading online at ElevenForum about people having issues with DISM ... /restorehealth on Build 26100.8972 and 26200.8972. Naturally, I had to check to see if I fell into that same boat. On the plus side, none of my machines at that build level threw an error for the command. On the minus, I observed a long DISM pause at 63% range in completing the sequence that stretched to 70% and a bit more. Copilot tells me this is the stage during which DISM downloads files needed to repair questionable items found in the component store.

Varying Times for Long DISM Pause at 63% Range

The lead-in graphic shows a completion time of 22m 55.301s for the command on my Flo6 desktop (MSI B550 mobo, AMD Ryzen 7 5800X, 64 GB RAM, RTX 3070 Ti). Other intervals I recorded include:

  • 13m 33.008s on AsusSnap (Zenbook A14, SnapDragon X Plus X1P-42-100, 16 GB RAM, Adreno graphics)
  • 8m 36.148s on Lenovo ThinkStation P3 Ultra (Core Ultra 9 285, 64 GB RAM, RTX 4000 SFF)

In this admittedly small sample, I see a strong relationship between CPU speed and completion time. That tells me there’s a lot of thinking going on while the /restorehealth operation is underway. Download volumes were all consistently in the 3-4GB range, as measured by download values from the Network Meter gadget from GadgetPack.

Skip WU, Try ISO

Copilot suggests further that pointing the /restorehealth command at a local ISO could speed things up. But it also says that “the ISO build must match 26200.x [the reference/focus build] closely.” The only way to do that right now is to build an ISO using UUPdump.net to match the 26200.9278 build all 3 PCs are running. That can easily take an hour or longer. My total time for all 3 was under 46 minutes.

Here in Windows-World, if you don’t pay (or spend time) one way, you’ll almost always spend it another. I took the WU route, and was glad all those DISM ... /restorehealth commands completed successfully. That’s good enough for me!

 

Facebooklinkedin
Facebooklinkedin

Examining Nerd Font Glyphs

Nerd Fonts patch popular programming fonts with thousands of extra icons. These icons live in the Private Use Area (PUA) and other reserved Unicode blocks. Terminals that load Nerd Fonts gain instant access to logos, arrows, file-type icons, weather symbols, and power glyphs. Have you ever wondered exactly which glyphs your installed font contains? The Show-NerdFontGlyphs PowerShell function answers that question fast. It is the key to examining nerd font glyphs, in fact, up close and personal (see lead-in graphic).

Script for Examining Nerd Font Glyphs

The script defines one function: Show-NerdFontGlyphs. It loops through 13 named glyph ranges and renders each glyph alongside its hex code point. It also arranges the output in a configurable column grid. The default is eight columns wide. That width fits comfortably in most terminal windows. Run it, and in seconds you have a full visual catalog of every icon your font supports.

Each section prints a cyan header, making it easy to scan. Each row shows the rendered glyph followed by its four-digit hex address. That pairing is the key feature. Specifically, if you spot an icon you want, note its hex value. Then, reference it in PowerShell with [char]0xXXXX. For code points above U+FFFF, use [System.Char]::ConvertFromUtf32(0xXXXX) instead.

Unicode Ranges Covered

The script covers 13 glyph families. Here’s a quick guide to each one.

  • Pomicons (U+E000 to U+E00A): This set holds 11 miscellaneous icons from legacy Powerline themes.
  • Powerline (U+E0A0 to U+E0B3): These glyphs power the core Powerline separators and branch symbols used in prompt themes worldwide.
  • Powerline Extra (U+E0A3 to U+E0D4, scattered): This range adds rounded, flame, and diagonal separator variants to extend the Powerline set.
  • Symbols (U+E5FA to U+E6B2): These general-purpose glyphs include file-type icons and folder symbols.
  • Devicons (U+E700 to U+E7C5): This section covers programming language and framework logos including Python, JavaScript, Git, and Docker.
  • Font Awesome (U+F000 to U+F2E0): This classic set delivers social, UI, and media icons from Font Awesome 4.
  • Font Awesome Extension (U+E200 to U+E2A9): These icons extend Font Awesome with additional symbols.
  • Octicons (U+F400 to U+F4A8): GitHub Octicons cover pull requests, issues, branches, and repository actions.
  • Font Logos (U+F300 to U+F372): This range holds OS and distribution logos including Linux distros, BSD variants, and Apple.
  • Power Symbols (U+23FB to U+2B58): These glyphs represent standby, power-on, sleep, and toggle functions from the Miscellaneous Technical block.
  • Weather Icons (U+E300 to U+E3EB): This section delivers sun, cloud, rain, snow, wind, and forecast glyphs.
  • Material Design (U+F0000 to U+F0200, first 512 only): These icons come from Supplementary Private Use Area-A and represent a subset of the Material Design set.
  • Codicons (U+EA60 to U+EBEB): Visual Studio Code uses these icons for debugging, source control, and editor UI elements.

Spotlight on U+E62A: Win11 Logo

One glyph deserves special attention: U+E62A. It sits inside the Symbols range (U+E5FA to U+E6B2) and renders as the four-pane Windows 11 logo. Furthermore, it behaves as a double-width glyph. In other words, it occupies two terminal columns rather than one. That property makes it ideal for building large logo art in FastFetch or other terminal info tools.

You reference it in PowerShell with [char]0xE62A. In a Nerd Font terminal, that expression produces the Windows logo glyph directly. Yesterday’s post on this site shows how to build a custom 8×8 FastFetch logo grid in Windows blue using this glyph.

Running the Script

Save the function to showglyphs.ps1. Next, dot-source it in your PowerShell 7 session and call it:

.\showglyphs.ps1
Show-NerdFontGlyphs

You can also adjust -Columns to fit your terminal width. Narrower windows work better with -Columns 4 or -Columns 6. The function handles code points above U+FFFF using [System.Char]::ConvertFromUtf32. As a result, it does not throw errors on supplementary characters.

Download the Script

Download the complete showglyphs.ps1 script directly from this post. Save it to your PowerShell scripts folder and dot-source it in your profile or on demand. Finally, pair it with a Nerd Font in Windows Terminal for the best results. CaskaydiaCove Nerd Font and JetBrainsMono Nerd Font are both excellent choices.

I wouldn’t have found the Win11 logo without this nifty little tool. Try it yourself, and be amazed at all the icon-like images that nerd fonts can offer. They’re amazing!

Facebooklinkedin
Facebooklinkedin

WinGet Misses ARM Browser Updates

If you run winget upgrade --all on an ARM-based Windows 11 PC (e.g. an Asus Zenbook A14), you may notice something odd: Chrome and Firefox don’t show in the upgrade list, even when they’re out of date. On an x64 desktop, winget catches them without fail. So what gives? Briefly put, and for various reasons, WinGet misses ARM browser updates for certain implementations.

It turns out there are four overlapping bugs and design gaps at play. All of them affect ARM64 PCs. None of them are your fault, either. But together they form a perfect storm that makes WinGet effectively blind to certain browsers. For now, anyway.

TLDR: On ARM64 Windows PCs, WinGet fails to detect and upgrade Chrome and Firefox due to four compounding issues: a name-normalization bug (winget-cli #6490), a registry hive mismatch, a broken ARM64 manifest entry for Chrome, and an architecture-selection bug (winget-pkgs #424881). Until Microsoft patches these, a handful of workarounds fill the gap. Here goes…

Diving in: Why WinGet Misses ARM Browser Updates

On x64 machines, the registry is simple: one hive, one architecture tag, and manifests that have been battle-tested for years. WinGet’s upgrade logic originates from that x64 worldview. Alas, things on ARM64 aren’t quite so simple, and all four failure modes described next come out of various diversions from the x64 situation.

Four Root Causes

  1. The ARP Name-Normalization Bug (winget-cli #6490)

Winget matches installed apps to its catalog by reading Add/Remove Programs (ARP) registry entries and normalizing display names. It strips “x86” and “x64” — but has no handling for “arm64” or “ARM64.” When Chrome or Firefox registers with an ARM64 architecture suffix on a Snapdragon device, winget cannot correlate it to the catalog entry and silently drops it. The app becomes invisible to winget upgrade.

  1. The Registry Hive Mismatch

ARM64 Windows splits app registrations across 3 registry hives:

 

Hive Contents Who Writes There
SOFTWARE\…\Uninstall Native ARM64 apps ARM64 installers
SOFTWARE\WOW6432Node\…\Uninstall x64-emulated apps x64 installers (Chrome, Firefox legacy)
HKCU\SOFTWARE\…\Uninstall Per-user installs Either architecture

 

If Chrome or Firefox were installed via an x64 installer — the only option before both browsers shipped native ARM64 builds — it lives in WOW6432Node. Winget, running as a native ARM64 process, reads the native hive first and, when name normalization is also broken, frequently misses those emulated entries entirely.

  1. The Broken Chrome ARM64 Manifest

Even when winget finds Chrome, the Google.Chrome manifest in the community repository lists an arm64 installer entry with a blank SHA256 hash. Winget requires a valid hash to verify any upgrade — blank means the ARM64 path is present on paper but non-functional. The Google.Chrome.EXE package ID does carry a properly populated hash, which explains why some users get inconsistent results depending on which package ID is in play.

  1. The Architecture Selection Bug (winget-pkgs #424881)

Even with a complete, valid manifest, winget’s upgrade logic has a documented bug where it selects the x64 installer over arm64 on Windows on ARM machines. Best case: you get the slower, emulated build pushed onto your ARM device. Worst case: the upgrade fails outright.

Viable WinGet Workarounds

Until Microsoft ships fixes, here are some WinGet options — from most precise to most blunt:

  1. Force the architecture explicitly: Use winget upgrade Google.Chrome --architecture arm64 and winget upgrade Mozilla.Firefox --architecture arm64. This bypasses both  correlation and selection bugs in one go.
  2. Use the Chrome EXE package ID: winget upgrade Google.Chrome.EXE --architecture arm64 hits the manifest entry that actually has a valid SHA256 hash for ARM64.
  3. Let the browsers self-update: Both Chrome (Google Update/Omaha) and Firefox (Mozilla Maintenance Service) are fully architecture-aware. Help → About in either browser triggers an immediate, correct ARM64 update — no winget involved, no ARM64 drama.
  4. Add --include-unknown as a catch-all: winget upgrade --all --include-unknown is a blunt instrument, but it sometimes remcatches apps that fail normal ARP correlation.

The real, true fix requires Microsoft to patch name-normalization and upgrade architecture-selection logic in winget-cli. Two of the four bug reports were filed in the last few days, so movement could come soon. Until then, –architecture arm64 is the cleanest workaround on your Zenbook A14 — or any other Snapdragon-powered Windows machine. In Windows-World, knowing where the bodies are buried is half the battle.

Facebooklinkedin
Facebooklinkedin

Flo6 Recovery Partition Cleanup

One of the quieter but genuinely useful maintenance tasks for any Windows 11 machine is verifying the WinRE recovery partition. When necessary, you can refresh bits and pieces. On my desktop (production) rig Flo6, that job came due recently when I discovered a one-version gap between the OS and the recovery environment. Here’s exactly what I did to perform Flo6 recovery partition cleanup.

Why Do Flo6 Recovery Partition Cleanup?

Flo6 was running Windows 11 25H2 (build 26200.9168). It’s current and fully patched. A quick reagentc /info at an elevated command prompt, however, told a different story about the recovery environment: Windows RE Version 10.0.26100.9168. That’s 24H2 — one full major version behind the OS.

This kind of mismatch is typical after an in-place upgrade. Windows Update doesn’t always push a matching WinRE update alongside the OS upgrade. The recovery environment still works, but keeping it in sync with the running OS is simply good hygiene.

Finding the Right Source Media

Fortunately, I had a Windows 11 25H2 bootable UFD on hand. It is ESD-USB labeled, FAT32 formatted, carries seven editions in a split WIM (install.swm + install2.swm, totaling ~5.6 GB compressed). A quick DISM query confirmed the match:

dism /get-wiminfo /wimfile:G:\sources\install.swm /index:6

Output showed Version: 10.0.26200 / ServicePack Build: 9168 — an exact build-for-build match with Flo6’s OS. The source media was confirmed.

DISM Workflow: Four Clean Steps

Split WIMs add a wrinkle:the/swmfile parameter won’t work with /mount-wim. The workaround is to export first, then mount the resulting single WIM. Here’s the sequence I ran from an elevated command prompt:

Step 1 — Export the Pro edition to a single WIM:

dism /export-image /sourceimagefile:G:\sources\install.swm /swmfile:”G:\sources\install*.swm” /sourceindex:6 /destinationimagefile:C:\temp_pro.wim

Step 2 — Mount read-only to C:\BootMount (a pre-existing empty directory):

dism /mount-wim /wimfile:C:\temp_pro.wim /index:1 /mountdir:C:\BootMount /readonly

Step 3 — Extract winre.wim to a temp location:

copy C:\BootMount\Windows\System32\Recovery\Winre.wim D:\Temp\Winre25H2.wim

Step 4 — Unmount and delete the temp WIM:

dism /unmount-wim /mountdir:C:\BootMount /discard
del C:\temp_pro.wim

Swapping the WinRE Recovery Partition Image

With the new Winre.wim extracted, swapping it into the recovery partition takes just a few commands using reagentc (note: the copy command runs into a second line here, but should be a one-liner when run at the command line):

reagentc /disable
copy /y d:\temp\winre25h2.wim r:\recovery\windowsre\winre.wim
reagentc /enable
reagentc /info

The leading screenshot above shows this exact sequence — disable, copy, enable, and the final /info verification — all completing successfully. Note that R:is the recovery partition, temporarily assigned a drive letter for this operation.

A Nuance Worth Noting

The final reagentc /info reported Windows RE Version: 10.0.26100.9168 , and still shows 24H2. This isn’t a failure. The winre.wim packaged inside a 25H2 OS install image is itself built on the 24H2 WinPE base.

Microsoft maintains WinRE on its own separate servicing track. The embedded winre.wim version doesn’t automatically match the OS build number. The WinRE is fully functional and properly enabled — the version stamp reflects WinPE infrastructure, not a gap in recovery coverage.

Bottom Line

The Flo6 WinRE recovery partition is now refreshed, re-enabled, and confirmed healthy: Status Enabled, location correct, BCD identifier registered, and local reinstall available. Total active time at the command prompt: under ten minutes.

If you haven’t checked your own WinRE status lately, reagentc /info is a fast, zero-risk first step — and now you know exactly what to do if the version number looks off. Here in Windows-World, checking is good, and verifying is better. Today, I’m in a good place. How about you?

Facebooklinkedin
Facebooklinkedin