Category Archives: PowerShell

Quick WLAN Profile Cleanup

I’ve known for a long, long time that the netsh wlan show profiles command lists known Wi-Fi networks on suitably equipped Windows PCs. Until now, I’ve periodically used that command to check how many I’ve got and how many I don’t really need. Now, thanks to Copilot’s “script on demand” abilities, I’ve got a script that walks me through the list. It offers a quick WLAN profile cleanup, so I can keep the ones I use, and deep-six the ones I don’t.

PowerShell For Quick WLAN Profile Cleanup

The screencap starts with the list of 7 known wi-fi networks on the Lenovo ThinkPad X380 Yoga. Of the 7 networks shown, I only need 2 of them.

The script (named wifiprofcln.ps1) walks through all known WLAN profiles for Wi-Fi networks, then asks whether to keep or delete each one. As you can see in the screencap, I deleted 5 and kept 2 of the 7 I started out with. Some were from hotels, others from offices, others from my cellphone provider’s hotspot network.

The Real Beauty of On-Demand Scripting

This is just a simple bit of throwaway PowerShell. The script is 40 lines long. It took Copilot less time to build it than it took me to tell it what I wanted the script to do. At one time, I would’ve been inclined to deliver this info as a recipe with the proper way to structure commands and let readers DIY their way through it. Now, I can put together and share a quickie one-off tool in minutes.

Say what you want about the evils of AI, the perils of hallucination or misalignment, or even existential threats. This kind of simple, straightforward use is easy, fast and pretty darn useful. Within scope and with a tight focus, it’s a complete boon to getting things done here in Windows-World. Use it carefully, to be sure, but use it you must!

Facebooklinkedin
Facebooklinkedin

More Discord Follies: Unactivated Download

Sometimes an update problem gets more interesting after the obvious fix succeeds. That just happened to me with Discord on Windows. WinGet insisted version 1.0.9267 was available, while my PC remained on 1.0.9266. Even stranger, forcing the upgrade did not change the reported installed version.

I tried WinGet, UniGetUI and Discord’s in-app updater. Nothing moved the needle. Eventually I performed a clean uninstall and reinstall. That exercise exposed what was really happening: version 1.0.9267 had downloaded, but Discord was still running 1.0.9266. That’s how I found myself engaged in more Discord Follies: unactivated download is present, but inert. WTF?

Unpacking More Discord Follies: Unactivated Download

The basic inventory command showed the mismatch clearly:
winget list --id Discord.Discord --exact --scope user

It reported 1.0.9266 installed and 1.0.9267 available. Discord was installed at user scope, which also produced an instructive side trip. An elevated WinGet session refused to uninstall the per-user package. Switching to a normal Windows Terminal session fixed that.

winget uninstall --id Discord.Discord --exact --scope user

After the uninstall succeeded, I checked for leftovers:

Test-Path "$env:APPDATA\Discord"
Test-Path "$env:LOCALAPPDATA\Discord"

Both returned True. With no Discord processes still running, I removed those directories and verified that both paths returned False. That gave me the clean slate I wanted.

The Clean Install Surprise!

Next came an explicit installation of the supposedly newer release:

winget install --id Discord.Discord --exact --version 1.0.9267 --scope user

WinGet found 1.0.9267, verified its installer hash and reported a successful installation. Yet another winget list still showed 1.0.9266 installed, with 1.0.9267 available. At first glance, that looked impossible.

The file system told a better story. I enumerated Discord’s version directories:

Get-ChildItem "$env:LOCALAPPDATA\Discord" -Directory -Filter "app-*" | Select-Object Name, FullName

There were two of them: app-1.0.9266 and app-1.0.9267. Checking the Discord.exe files confirmed that each directory contained the version its name advertised. Again: WTF?

Installed Is Not Activated, Apparently

The decisive check was to examine the running processes instead of trusting package inventory alone:

Get-Process Discord | Select-Object Id, Path,
@{N='FileVersion';E={$_.MainModule.FileVersionInfo.FileVersion}}

Every running Discord process came from app-1.0.9266. I then checked the per-user uninstall registration:

Get-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
Where-Object DisplayName -eq 'Discord' |
Select-Object DisplayName, DisplayVersion, InstallLocation, UninstallString

Windows likewise registered Discord as version 1.0.9266. In other words, WinGet was not hallucinating. Version 1.0.9267 really existed on disk, but 1.0.9266 remained the registered and active release.

The Nub of This Discord Folly Is…

Discord’s current generic stable update manifest identifies 1.0.9267 as the host version. I also found installation-specific manifest results that still identify 1.0.9266. That makes staged update selection a plausible explanation for this split state, though the local evidence alone doesn’t completely illuminate  Discord’s rollout policy.

Here, the important lesson is more general. When an updater says success but inventory disagrees, inspect three layers: package registration, files on disk and the executable that’s actually running. Those views might disagree: here they did so spectacularly.

For now, I’m leaving both Discord directories alone. Manually deleting the active release or rewriting its registration would create more, not less

Discord’s current generic stable update manifest identifies 1.0.9267 as the host version. We also found installation-specific manifest results that still identify 1.0.9266. That makes staged update selection a plausible explanation for the split state, although the local evidence alone cannot prove Discord’s rollout policy.

The important lesson is more general. When an updater says success but inventory disagrees, inspect three layers: package registration, files on disk and the executable actually running. Those views can disagree, and here they did spectacularly.

For now, I am leaving both Discord directories alone. Manually deleting the active release or rewriting its registration would create more, not less uncertainty. Here in Windows-World, sometimes the best troubleshooting means knowing exactly why you should stop troubleshooting. I’m done for now, and will wait to see what Discord does next. Sigh.

Further Reading

Discord stable Windows x64 update manifest

Discord Support, Windows Corrupt Installation

Facebooklinkedin
Facebooklinkedin

Checking Hotfix Can Beat Package Check

After reading about KB5127936 and its Cloud Rebuild facility recently, I wondered how many of my production level PCs already sported this Preview CU. So I asked Copilot to craft me some PowerShell to check. Along the way, I learned that: (a) some methods are better than others, and (b) that there are many ways to request such information. It’s also how I learned that checking hofix can beat package check info, depending on what you need.

My first query looked perfectly reasonable:
Get-WindowsPackage -Online | Where-Object PackageName -match '5127936'
Alas, that request returned no output. Such a result could tempt an administrator to conclude that the update was absent. Here, that conclusion would be wrong.

Why Checking Hofix Can Beat Package Check

Turns out the afore-cited PowerShell command (which uses DISM under the hood) assumes that the string  “KB5127936” appears in the package metadata. It does not, as it turns out.

However, this simpler command
Get-HotFix -Id KB5127936
produces a direct hit. You can see the outcomes of both commands in the lead-in screencap. After Get-Hotfix, P16 reported KB5127936 as Update, installed by NT AUTHORITY\SYSTEM on October 29, 2026. For the question I was asking, that was exactly the information I needed.

Why the difference? Microsoft documents Get-HotFix as a cmdlet for retrieving installed hotfixes. It uses  Win32_QuickFixEngineering WMI class, whose -Id parameter accepts a hotfix ID. Microsoft even provides an example specifically for verifying whether an update is installed.

In other words, if I start with a KB number, Get-HotFix gives me a KB-oriented lookup. Good stuff!

Get-WindowsPackage Asks Something Different

Get-WindowsPackage is not broken, nor did DISM somehow miss the operating system update. Microsoft describes this cmdlet as a way to obtain information about packages in a Windows image. With -Online, that targets the running Windows installation.

The distinction matters because PackageName is the name of a servicing package inside the image. It is not promised to be the public KB identifier with which its labeled. Microsoft also notes that Get-WindowsPackage cannot provide detailed package information for .msu files, only .cab files. And KB5127936 arrives in .msu form.

Thus my pipeline was really asking, “Does any returned package name contain the characters 5127936?” The empty result answered that narrow question. It did not establish that KB5127936 was missing. And that’s because the package data omits that string. Sigh.

Match the Cmdlet to the Question

This suggests a useful rule of thumb. When somebody hands you a KB number and asks whether that update is installed, try Get-HotFix first:  Get-HotFix -Id KB5127936

For scripts, I like a quiet Boolean-style test:
if (Get-HotFix -Id KB5127936 -ErrorAction SilentlyContinue) { 'INSTALLED' } else { 'NOT FOUND BY GET-HOTFIX' }
That wording is deliberately cautious. Get-HotFix is not a universal inventory of everything Windows Update has ever installed, either. Microsoft defines its scope through QuickFixEngineering. Absence from that view should trigger another check, not a final verdict.

Package Checks Retain Their Value

When I am servicing an online or mounted Windows image, inspecting package identities, or working with CAB-based packages, Get-WindowsPackage remains the right tool. It answers a package-servicing question rather than a KB-history question.

That P16 session reinforced an old Windows lesson: command output only makes sense in the context of the question asked. Here, Get-WindowsPackage told me there was no package name matching my KB string. Get-HotFix told me the update associated with that KB was installed.

Sometimes the simpler check really is the better check. On P16, it certainly was. Here in Windows-World simple is not only faster and easier; it’s a minor but useful labor-saving device!

Further Reading

Microsoft Learn: Get-HotFix (Microsoft.PowerShell.Management)

Microsoft Learn: Get-WindowsPackage (Dism)

Facebooklinkedin
Facebooklinkedin

Scripting Macrium Rescue Disk Repair

Here’s something I’ve been chewing on for the past few weeks. I’ve had help from a persistent and curiously passive interlocutor at ElevenForum.com. I still use Macrium Reflect to back up at least half of my PC fleet.

For whatever reason, the Macrium Software team has yet to update its Rescue Disk creation to accommodate Secure Boot requirements. That’s what led me to scripting Macrium Rescue Disk repair using Copilot and PowerShell. Therein hangs today’s post…

What’s Involved in Scripting Macrium Rescue Disk Repair?

Basically, I asked Copilot to build a PowerShell script to fix the Macrium Rescue Disk for Secure Boot. Why? I use Secure Boot on all my PCs.

I can’t restore a Reflect boot image unless the Rescue Disk will actually BOOT the target PC. Only then can I perform the restore operation.

For the record, I’m using Macrium Reflect X, not the older versions numbered 8.x or lower. Working with Copilot, I had to chunk through three, then four versions before the script worked on my PC.

That PC is Flo6, my B550-based desktop. It has an MSI MAG Tomahawk MAX motherboard, Ryzen 7 5800X, NVIDIA RTX 3070 Ti, and 64GB RAM.

Using Copilot Requires LOTS of Trial and Error

The output from the script itself documents what it does pretty well, so I reproduce it here:

==============================================================
  fixmrrdv6.ps1  --  Secure Boot SVN Repair Tool              
==============================================================
   [>>] Validating target drive: G:                                                                                                                       
       [OK] Drive label  : ESD-USB                                                                                                                       
       [OK] File system  : FAT32
       [OK] Size         : 14.4 GB
       [!!] Label 'ESD-USB' does not contain MACRIUM -- verify correct drive.
   [>>] Locating boot.wim on rescue media                                                                                                                 
       [OK] Found WIM    : G:\sources\boot.wim                                                                                                           
       [OK] WIM size     : 557.2 MB
   [>>] Locating Secure Boot source files from live Windows
       [OK] External source: C:\Windows\Boot\EFI_EX\bootmgfw_EX.efi
       [OK] WIM source     : C:\Windows\Boot\EFI_EX\bootmgfw_EX.efi
       [OK] Winload source : C:\Windows\System32\winload.efi
       [OK] Backup root    : C:\Users\ed\AppData\Local\Temp\FixMRRD_Backups_20261026_155946
   [>>] Replacing external bootmgfw.efi on USB
       [OK] Backed up: bootmgfw.efi -> C:\Users\ed\AppData\Local\Temp\FixMRRD_Backups_20261026_155946\ExternalUSB\bootmgfw.efi
       [OK] Replaced: bootmgfw.efi from EFI_EX\bootmgfw_EX.efi
   [>>] Patching boot.wim (index 1) with Secure Boot files
       [OK] Mount directory  : C:\Users\ed\AppData\Local\Temp\FixMRRD_WimMount_20261026155946
       [!!] Mounting WIM (this may take a minute)...
       [OK] WIM mounted successfully.
       [OK] Backed up: bootmgfw.efi -> C:\Users\ed\AppData\Local\Temp\FixMRRD_Backups_20261026_155946\WIM\bootmgfw.efi
       [OK] Patched: bootmgfw.efi
       [OK] Backed up: bootmgfw_EX.efi -> C:\Users\ed\AppData\Local\Temp\FixMRRD_Backups_20261026_155946\WIM\bootmgfw_EX.efi
       [OK] Patched: bootmgfw_EX.efi
       [OK] Backed up: winload.efi -> C:\Users\ed\AppData\Local\Temp\FixMRRD_Backups_20261026_155946\WIM\winload.efi
       [OK] Patched: winload.efi
       [!!] Committing and unmounting WIM (this may take a minute)...
       [OK] boot.wim patched and committed successfully.

==============================================================
  All done! Secure Boot SVN repair completed successfully.
  Run check_bootmedia.ps1 against the USB to verify ALLOWED.
==============================================================

To debug this script, I kept catching error messages as it ran, reporting them to Copilot, and re-running rewritten versions until it produced a clean Rescue Disk on Flo6. How did I define that? By running Garlin’s check_bootmedia.ps1 script against it until it returned a clean result (all boot managers use CA 2023, show up as ALLOWED, use SVN 12.0). And indeed it works on Flo6 right now just fine.

What Works for Me, May Not Work for YOU

What I’ve learned from my interlocutor on ElevenForum.com is the following. Though the script runs on Flo6, it doesn’t run on his PC. Based on the errors he’s reporting, I think I know what’s going on. Writing files into a mounted WIM is tricky, as I’ve learned, and requires extensive mucking about with permissions. System ownership must be taken over, writing work done, then restored to pristine condition. This takes work and some understanding of how ACLs and the Trusted Installer work in modern Windows OSes (10 and 11, basically, though the same behaviors also hold in current Windows Server versions).

When things go wrong for me with a script like this one, I attack them with Copilot until they work. My interlocutor, apparently, isn’t inclined to do this himself. But that’s what it takes to make things work on YOUR PC here in Windows-World: a dogged determination to keep iterating until the error messages no longer appear, and the resulting functionality does what you want it to do.

Post some comments here to let me know if you’re OK with this “exercise is left to the reader to fully complete” approach. Those who really want the script to fix their Macrium Reflect X Rescue Disks can ask for it, and I’ll send it to them. But they’ll have to be ready to make it work on their PCs to achieve its intended use!

Facebooklinkedin
Facebooklinkedin

MediaMonkey Version Info Fools WinGet

MediaMonkey recently taught me another lesson about package managers: version information has to agree at both ends. Otherwise, automation can outstrip itself. Indeed, I’ve just witnessed how truncated MediaMonkey version info fools winget into a looping update.

I had already run a broad WinGet update using winget upgrade –all –include-unknown. MediaMonkey was included and its update completed successfully. Later, though, WinGet proffered MediaMonkey again. That follow-on install also completed successfully, leaving me wondering why an already updated application looked stale.

How Truncated MediaMonkey Version Info Fools WinGet

The lead-in screenshot makes a mismatch plain. WinGet identifies the package as VentisMedia.MediaMonkey.2024. Its list output reports the installed Version as “2024,” but Available is “2024.2.2.3222.” From WinGet’s perspective, those strings do not match.

A PowerShell registry query settles the question from the installed-software side. MediaMonkey 2024 records DisplayVersion simply as “2024.” The same entry identifies Ventis Media Inc. as Publisher and points to the 32-bit Program Files installation location.

Get-ItemProperty `
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*,
HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*, `
HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* `
-ErrorAction SilentlyContinue | `
Where-Object DisplayName -Like '*MediaMonkey*' | `
Select-Object DisplayName, DisplayVersion, Publisher, InstallLocation, PSPath

That is the crux of the problem. The installed application advertises “2024.” The WinGet package advertises “2024.2.2.3222.” Thus, WinGet continues to find the need to upgrade even after installing the latest package.

A Blocking Pin Breaks the Loop

Rather than let routine upgrade runs keep revisiting MediaMonkey, I added a blocking pin against the package ID:

winget pin add --id VentisMedia.MediaMonkey.2024 --blocking

The next winget pin list confirms the result. MediaMonkey 2024 appears with version 2024, source winget, and pin type Blocking.

That choice is deliberately stronger than an ordinary pin. Microsoft documents a blocking pin as preventing upgrades through both “winget upgrade –all” and a direct package upgrade. The package must be unpinned before a normal WinGet upgrade can proceed, although the force option can override this specific pin behavior.

Watch, Wait, Then Unpin When It’s Time

For now, blocking is exactly what I want. The installed MediaMonkey is current based on the package I just installed, while its reported version remains too broad and unspecific for WinGet to compare cleanly.

The next move is patience. I will periodically check MediaMonkey and the WinGet package metadata. When a genuine new release appears, I can remove the block, run the upgrade, and see whether the installed DisplayVersion finally reports a fully qualified build number.

If that happens, WinGet should again have comparable version strings to work with. If not, the blocking pin can go right back on.

Version Metadata Makes the Difference

Yesterday’s episode is a useful reminder that WinGet can only act on available version information. A successful install does not guarantee the application and package catalog describe the result identically.

Here, two command-line checks tell the whole story. First, winget list exposes the disagreement. Second, PowerShell confirms what Windows knows about MediaMonkey. Until those values line up, a blocking pin turns an annoying repeat upgrade into a controlled watch-and-wait problem. Case closed, at least for now. Here in Windows-World it’s been added to the list of things I must watch and remember. It’s a big and pretty active one, as Windows pros already know…

Facebooklinkedin
Facebooklinkedin

Powershell Update Goes Sideways

Interesting doings in the Windows Terminal PowerShell world. Running WinGet in that environment just now, I updated PS. Not only did that activity produce an “Installation abandoned” error msg, it initially threw up cmd prompt instead of PS when I clicked the plus sign to launch a new WinTerm session. Alas, it looks like this PowerShell update goes sideways (and more so on some PCs).

Ways PowerShell Update Goes Sideways

First, let’s survey the landscape. Windows PowerShell 5.1 is built into Windows and goes nowhere. It is a system component, not something you update through a package manager. PowerShell 7.x is a completely separate, side-by-side install. It lives in its own directory and uses its own executable, pwsh.exe.

The standard command for updating PowerShell 7.x is clean and simple. You open a terminal and run winget upgrade --id Microsoft.PowerShell. However, what looks simple on the surface can hide a lot of failure modes underneath.

Updates can stall mid-stream, roll back without a clear explanation, or appear to succeed while doing nothing at all. That last scenario is especially maddening. You see a success message, then run pwsh --version and get the old build number staring back at you. Something broke during the install, and winget did not catch it.

Oh No! Installation Abandoned…

I’ve seen this error message (see lead-in graphic) before. Normally, that means the PS installer has lost its connection to Winget via PowerShell and WinTerm. You can often see the PS installer window open, still running, and finishing its work. Closing, then re-opening WinTerm usually sets things back to rights.

Not this morning, on my Flo6 desktop (B550 mobo with AMD Ryzen 7 5800X CPU). After the upgrade, a new PS session launched cmd prompt instead. WinTerm lost its path to the pwsh.exe executable. When I went to look at its profile, it showed as empty. So I had to delete it, and recreate it, then point to the PowerShell 7 icon. That fixed things right up.

That Worst Case Isn’t Ubiquitous

When I updated PS on the Lenovo ThinkPad P16 Gen 1 mobile workstation, I got the same “installation abandoned” error message. But when I opened a new PS session (using the menu bar “+” control) the new version popped right up in a proper PowerShell pane.

I’m not sure why some machines act out more than others when the PS install goes sideways. Shoot! It could have been cosmic rays. But whatever happens, you can fix it if you check the profile and make sure it’s properly defined. Here in Windows-World knowing what to fix and how to fix it goes a long, long way. This morning, it went far enough to set things back up properly on Flo6. May it do the same for you, should you need it to!

One More Thing…

Just ran the same update on the ASUS Zenbook A14 (Snapdragon X ARM CPU). Completed successfully! I’m starting to think that platform diffs may play into this situation. The AMD platform failed and carried a persistent error state. The Intel platform failed, but recovered. And the ARM platform sailed right thru. Go figure!

 

Facebooklinkedin
Facebooklinkedin

Fixing Macrium Rescue Disk

Microsoft updated its Secure Boot revocation database (DBX) in mid-2026. That update requires Boot Manager binaries to carry a minimum Security Version Number (SVN) of 11.0. It also bans the older “Production PCA 2011” signing certificate. Rescue media that Macrium Reflect X builds fails both tests out of the box. That means with Secure Boot enabled, the Reflect’s boot media won’t work. That’s why I’m writing today about what’s involved in fixing Macrium Rescue Disk.

Most important, this post walks you through a PowerShell script named fixmrrd.ps1 that fixes all three BANNED files in a single pass. Buckle up! There’s LOTS of ground to cover…

Why Fixing Macrium Rescue Disk Is Necessary

Macrium Reflect X builds its WinPE rescue environment from the Windows ADK (Assessment and Deployment Kit). The ADK ships once per Windows release and never gets Patch Tuesday updates. Its boot files stay frozen at the SVN level they carried on release day.

For Windows 11 24H2, the WADK 11 ADK shipped with boot files at SVN 2.0. The current DBX floor is SVN 11.0. That nine-version gap is the core problem that requires fixing.

The standard boot manager file, aka bootmgfw.efi that lives under C:\Windows\Boot\EFI\ also carries the banned Production PCA 2011 certificate. Even when the SVN is correct, that certificate triggers a hard BANNED result. Garlin’s check_bootMedia.ps1 diagnostic tool makes both problems visible immediately.

Introducing fixmrrdv2.ps1

fixmrrdv2.ps1 bridges the gap Macrium leaves open. It pulls every replacement file from your live, fully patched Windows 11 installation. Those files already meet the SVN 11.0 requirement and carry the correct Windows UEFI CA 2023 certificate. It’s a v2 version because @Monica1491 over at ElevenForums pointed out an error that I fixed.

Here is what the script does at each step:

  1. Validates the target USB drive and confirms it carries a MACRIUM label.
  2. Locates boot.wim on the rescue media, typically at sources\boot.wim.
  3. Identifies three source files from your live Windows installation: bootmgfw.efi, bootmgfw_EX.efi, and winload.efi. It reports the version number of each file.
  4. Replaces the external bootmgfw.efi on the USB EFI partition. It uses the EX variant (bootmgfw_EX.efi) as the source — not the standard bootmgfw.efi. The standard file carries the banned Production PCA 2011 certificate. The EX variant carries the required Windows UEFI CA 2023 certificate.
  5. Mounts boot.wim using DISM. Then it adjusts ACLs on the internal target files. WIM images lock their contents with restrictive ACLs. Even Administrator hits an access-denied error without a takeown and icacls step first.
  6. Replaces bootmgfw_EX.efi and winload.efi inside the mounted WIM.
  7. Commits the changes and unmounts the WIM. If any step fails, DISM discards the mount and leaves the original WIM intact.

The script backs up every replaced file with a timestamped .bak_ suffix before touching it. Color-coded [OK], [!!], and [FAIL] status lines show progress at each step.

Before You Run the Script…

There are four prerequisites apply before you run fixmrrdv2.ps1.

  • Run as Administrator. DISM mount operations require elevation.
  • Use Windows PowerShell 5.1 (powershell.exe). Do NOT use PowerShell 7.x (pwsh.exe). The DISM /Mount-Image command does not work correctly under PowerShell Core. The script detects PS 7.x automatically and exits with a clear message if you start it from the wrong shell.
  • Your Macrium rescue USB must be plugged in and assigned a drive letter. Note that letter before you start.
  • Your execution policy must allow local scripts. Run this in an elevated PS 5.1 window if needed:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Download fixmrrdv2.txt from its OneDrive link (read only). Rename it to fixmrrd.ps1. Place it in a convenient location, such as C:\tools\scripts\.

Running the Script…

Open an elevated Windows PowerShell 5.1 window. Navigate to the folder holding fixmrrd.ps1. Then run:

.\fixmrrd.ps1 -TargetDrive G:

Substitute your actual rescue drive letter for G:. If you omit -TargetDrive, the script prompts you for it.

The script runs without further interaction. The DISM commit step takes the longest — typically 30 to 60 seconds. Do not interrupt that step.

Each replaced file gets a timestamped .bak_ backup before the script writes anything new. You can restore any original file by renaming the matching backup.

One timing note: the script reports source file versions from C:\Windows\Boot\EFI\ and C:\Windows\Boot\EFI_EX\. You may notice the version number on the USB after copy differs slightly from what the script reported. This is a FAT32 metadata quirk. The SVN level is what really matters, and transfers correctly.

Verifying Results

Run Garlin’s check_bootMedia.ps1 against the drive when the script finishes:

.\check_bootMedia.ps1 G: -audit -verbose

A correctly fixed drive shows all three boot files as ALLOWED:

USB Drive g: "MACRIUM_PE"
    Windows Boot Manager [Windows UEFI CA 2023] is ALLOWED.
        g:\EFI\Microsoft\Boot\bootmgfw.efi
        File Version: 28000.367, SVN 11.0

    boot.wim:1 (WinPE 26100.1)
        Boot Manager [Windows UEFI CA 2023] is ALLOWED.
            \Windows\Boot\EFI_EX\bootmgfw_EX.efi
            File version: 28000.367, SVN 11.0

    \Windows\System32\winload.efi is ALLOWED.
        File version: 26100.9444

If any file still shows BANNED, check that you ran the script in PowerShell 5.1 with elevation. Re-run if needed — the backup files let you roll back safely.

The Net-Net: Working Rescue Disk

This is a product gap in Macrium Reflect X, not a user error. Macrium builds from ADK components that Microsoft does not update through Patch Tuesday. The recoverydrive.exe tool that ships with Windows sources its boot files directly from the live OS. Macrium does not. Until Macrium ships a fix that closes that gap, fixmrrd.ps1 fills it. It ticks me off, and that’s why I decided to script my way around it.

Keep this script on hand. The next time you rebuild a Macrium rescue drive, perhaps after a major Windows update or a new ADK release, you will need it again. The whole process takes under two minutes once you know the steps. Here in Windows-World, when vendors don’t fix their stuff, we users must sometimes step in to help out. Cheers!


Facebooklinkedin
Facebooklinkedin

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