Category Archives: PowerShell

Sussing Out Doubled-Up PowerShell

Here’s an interesting one. After running winget upgrade on Friday afternoon, I noticed something interesting. Even though I’d already upgraded that particular PC to PowerShell version 7.3.9, it still showed a version of 7.3.8 in need of an upgrade. Immediately, I started sussing out doubled-up PowerShell. As you can see in the lead-in graphic it was a case of “parallel versions.” Even though 7.3.9.0 is clearly installed (PowerShell 7-x64), so is 7.3.8 (PowerShell 7.3.8.0).

After Sussing Out Doubled-Up PowerShell,
Bye-Bye 7.3.8!

Turns out that 7.3.9 has some install changes. That means winget won’t simply upgrade the software. One must run winget uninstall, then winget install to do this particular round of the PowerShell upgrade dance. You can see this at work in the next screencap, which shows:

(a) notification from PowerShell that a new stable release is ready for download (white background against black text up top)
(b) notification from winget that “install technology is different” for new PowerShell release, so uninstall/install maneuver is needed

Sussing Out Doubled-Up PowerShell.winget-info

PowerShell is pretty clear that winget upgrade can’t handle this without extra maneuvers.

Thus, one approach here would be to run this sequence of wingets:

winget uninstall Microsoft.Powershell
winget install Microsoft.Powershell

The first removes the old version and the second installs the current (new) one. Easy-peasey, right?

Take the Long Way Home

The way I see things, there’s another choice when this kind of thing happens. The PowerShell installer file at GitHub (or the equivalent link shown at the top of the screencap: https://aka.ms/PowerShell-Release?tag=v7.3.9) not only installs the new PowerShell version, it also removes the old one. So I went ahead and ran PowerShell-7.3.9-win-x64.msi on the same machine where I captured the preceding screencap. I closed PS manually, instead of having the installer do it. Then I ran winget upgrade again. And sure enough, the doubled-up version once again appears!

It gets more interesting. I ran winget uninstall MIcrosoft.PowerShell –version 7.3.9.0 to remove the older version. This time, I let the (un)installer attempt to close PowerShell. It failed, and showed an “uninstallation abandoned error” (see next screencap).

Winget drops the ball trying to uninstall the newer version from inside that version! [Click image for full-sized view.]

Go with What Works

OK, I want to run the new version. But I also want to remove the older one. That cycles me back to the original screecap at the head of this blog post. If you go to Settings → Apps → Installed apps, you can easily excise older PowerShell versions from there. So that’s what I did. And presto: no more winget notifications that 7.3.8.0 needs an upgrade to 7.3.9.0.

One more thing: on another test machine (one running a preview version of PowerShell) I successfully used winget to uninstall 7.3.8.0 and then follow up with a successful 7.3.9.0 install. I think this worked because PowerShell 7.3.9.0 didn’t attempt to uninstall or install itself. That said, I did also have to manually install a new profile so I could make 7.3.9.0 my default PS selection afterwards. It’s always something, right?

Note added November 1: Do It From Command Prompt

On another test PC just now, I opened Windows Terminal. Then after opening a Command Prompt tab, I closed the open (default) PowerShell 7.3.8.0 tab. After that I was able to use winget to uninstall the older PS version and install the new one. This required no  new profile shenanigans. It’s my recommended approach until the PS team gets this fixed (I got confirmation from an MS contact yesterday that yes, this is a known thing and they’re working on it).

Facebooklinkedin
Facebooklinkedin

Syntax Errors Derail PowerShell JSON Edits

I’ve just completed a fascinating project for TekkiGurus: a five-part series on customizing and extending Windows Terminal. For the 5th and final part, I decided to build PowerShell scripting that would handle such customizations I use as don’t fall under the settings.json umbrella. Ironically, one of those tasks involved editing that very file to change the default font. That’s when I saw syntax erors derail PowerShell JSON edits, as shown in the lead-in graphic. Let me explain…

How Did Syntax Errors Derail PowerShell JSON Edits?

I started off my project by asking Copilot to present me with some initial PowerShell commands to handle the following tasks:

1. Download, install and set up Jan DeDobbeleer’s outstanding OhMyPosh prompt customization tool. This turns out to be a more complex task than it might seem, because it requires downloading, unzipping and copying Nerd Fonts into C:\Windows\Fonts, adding an invocation to the PowerShell Profile script, dealing with OhMyPosh, and then selecting a Nerd Font as the WT default.

2. Download, install and add the colortool executable to a default Windows path. Colortool is a GitHub project that provides information about Windows Terminal color assignments for text and text backgrounds. This one was pretty straightforward.

3. Install the winfetch utility that shows WT color schemes, system info, text colors, and a few other odds’n’ends. This required only one line of code, so easy-peasey.

The error showed up at the end of my PS sequence for the OhMyPosh tasks (I’ll refer to this as OMP from now on). Seems that Copilot’s code included two errors that it took me some time to find. First, the object sequence for the default font that OMP required turned out to be the string “.profiles.defaults.font.face” rather than the truncated version that Copilot provided (“.profiles.defaults.font”). Also, it used an alias for the default Nerd Font I chose rather than its full name — that is “CaskaydiaCove NF” instead of “CaskaydiaCove Nerd Font”. Interestingly, this alias worked in Windows 10, but not in Windows 11 (there, only the full name would do).

Errors Found Are Easily Fixed

It took me a while to figure this out because I couldn’t find exact documentation to match my problems precisely. I figured out the object sequence by examining the json.settings file from another Windows PC that had the default already set and following the sequence of the object name hierarchy in use in that file. In other words, I noticed a face property in that file that was missing from my rewritten json.settings file. No wonder it wouldn’t save.

Once I made that change, I got another error message (from Windows 11) that reported it couldn’t find a font named “CaskaydiaCove NF.” I so looked in C:\Windows\Fonts, and sure enough the font name in Explorer is actually “CaskaydiaCove Nerd Font.” And again, once I made that change things worked properly.

As the old saying goes: “It’s always easy when you know how.” It took me a while to get to the last detail in the “how” part, but indeed, it was dead easy after that. Things go that way a lot in Windows-World, especially when writing code or command line instructions. I’m just glad it’s working now!

One More Thing: Replacing Munged JSON File

On the machine where I made the object reference error, settings.json remained munged. It kept throwing errors each time I started up WT or PowerShell. So I  researched the topic and learned that if you open settings.json in a text editor, then delete the whole thing, WT will rebuild that file from programmed defaults when an empty file gets saved. That put my WT and PowerShell environments back to rights, and I was then able to get the corrected script to run to completion on that PC.

I’ll observe that if you’re going to edit settings.json in PowerShell on a Windows PC, it’s a good idea to have a backup at hand to replace that file. I’m learning that it’s kind of like working on the registry, where changes can have even more serious and dire side effects. Cheers!

Facebooklinkedin
Facebooklinkedin

Reboot Fixes Winget Hiccup

I have to laugh. If you take a look at the lead-in graphic you might be tempted to believe something amiss with winget. I was yesterday when this happened on one of my test PCs. So naturally, I tweeted (X’ed?) an MS colleague who runs the winget team. About 5 minutes later he responded with “Try a reboot!” Seems that others had been reporting similar woes amenable to this approach. To my chagrin, indeed a reboot fixes winget hiccup — this time, at least. Sigh.

If Reboot Fixes Winget Hiccup, Then What?

That adds another thing I need to try before bothering the developers another time. And, if that works for me (and some few others), it might also work for you, too. Thus, it should become a part of the normal troubleshooting routine.

Indeed, I had closed and re-opened Windows Terminal prior to contacting the team. And it hadn’t done the trick this time. In fact, I even uninstalled and reinstalled winget and that hadn’t worked, either — as you can see in the lead-in graphic.

Had I known then what I now know, I would’ve tried the reboot before those other more severe fixes. And it would have worked. Thus, the next time winget goes wonky on me (especially after an update) I’ll be sure to reboot my PC and trying again before sounding the alarm.

Interesting, eh? Things may not always look simple or obvious in Windows-World. Thank goodness they may sometimes be both, and amenable to a simple solution. All hail the “three-fingered salute” (remember when CTRL-ALT-DEL would force reboot a PC?) There’s no school like the old school!

Note Added October 10 (early PM hours)

As fate would have it, MS pushed an update to PowerShell today for version 7.3.8 through WU. After it updated my problem test PC, the same issue recurred: winget source was essentially not working. None of my previous fixes (reboot, uninstall & reset sources) worked. I had to force install the current production version (1.6.2771) over the current preview version (1.7.2782) to get things working properly again. Funny that this problem should happen on the very day I attempt to document a different issue. Amazing!

Facebooklinkedin
Facebooklinkedin

Using Copilot Based PowerShell

As an experiment, I’m using Copilot to generate PowerShell commands to complete specific tasks. It’s all centered around scripting to customize Windows Terminal to add fonts, applications, and settings for a specific configuration. Using Copilot based PowerShell isn’t just a “load and go” operation. I’m having to understand and alter code to make sure it runs on both Windows 10 and 11 PCs. So far, I can’t say it’s faster than hacking it out from scratch. But I can say “very educational.”

Using CoPilot Based PowerShell, Step by Step

I’m stepping through the PowerShell code that Copilot presents for handling my specified tasks line by line. In some cases, I’m simplifying by making more direct assignments to variables and manipulating them in the scripts. In other cases, I’m cleaning up minor syntax violations (quotes around string values where they’re not needed, and so forth). In still other instances, I’m figuring out how to complete commands “silently” (supressing user interaction).

But most of what I’m getting is pretty usable. As somebody who’s written plenty of “real code” (Java, JavaScript, Perl, Python and more) this is an interesting way to expand my PowerShell chops. If you’ve got some minor automation to handle — that’s how I’d characterize my current quest — you might find this helpful, too.

Fruits of This Labor…

I’m working on a story for TekkiGurus. I will probably finish up this week, but it takes two-three weeks to get through the editorial pipeline. Thus, you should see a story there from yours truly near month’s end (October 2023, that is). My working title is Creating and Sharing Windows Terminal Profiles Across PCs. Stay tuned, and I’ll plug a link in (and correct the wording, if need be) when it’s up.

Facebooklinkedin
Facebooklinkedin

Avoiding Windows Self-Update Traps

Think about it. When a program needs an update, sometimes what’s doing the update and what’s getting the update may be related. This gets interesting. Windows itself is a pretty good example. This explains why reboots are required to install  an OS, and often when updating same. Simply put, the pieces being working on cannot also do the work on themselves in many cases. Applications, apps, and so forth can also fall prey to the same things (think about installing an installer). Thus, avoiding Windows self-update traps is something of a balancing act.

Example: Avoiding Windows Self-Update Traps

I saw a great example of an artful dodge around this problem yesterday, as I was using Winget to update Windows Terminal (WT). Take a look at the lead-in graphic. It shows the WT update progress. Note that the last instruction at the end of that process reads:

Restart the application to complete the upgrade.

That’s exactly the kind of maneuver that’s necessary. It allows the currently running code for a program (or OS) stop running. Then, the newly-updated or installed code for the same program (or OS) can take over and start doing its thing.

Counter-Example: PowerShell

Back in June, I wrote a blog post here entitled WinGet Upgrade PowerShell Shows Cancelled. It shows what can — and sometimes still does — happen when the tail end of the installation process fails to complete and exit cleanly. I know the PS team is working on this, but this shows that self-updates do pose occasionally tricky problems.

I’m glad to see the WT take the high road and suspend the final steps of install or upgrade until it’s safe to do so. I’ll be gladder still when the PS team eventually follows suit (as I’m sure they will). In the meantime, I did find a workaround: if you open a Command Prompt session and run the winget PS upgrade there, no “cancelled” (or other error messages) result. Good enough for me, for now!

Facebooklinkedin
Facebooklinkedin

Update Trick Delivers Clean PS 7.3.7 Install

OK, then, Here’s an interesting way to handle the September 19 update for PowerShell, from 7.3.6 to 7.3.7. Indeed this specific update trick delivers clean PS 7.3.7 install. I’ve run into minor glitches on previous up-versions, because I was using PowerShell to update itself. It would show cancelled as its final update status, as the old runtime had to fall over to get itself out of the way for the new one.

You can see this at work in the lead-in graphic. It shows the Installer running to update PowerShell as a pop-up within the PS windows itself. In fact, it runs to completion without issues. Why? Because I closed the open default PS session and ran the PS update inside an Administrative Command Prompt session instead.

Which Update Trick Delivers Clean PS 7.3.7 Install?

Because PS essentially interferes with itself if it runs the upgrade from one version to the next, the trick is NOT to use PowerShell. That’s why I switched to Command Prompt instead, and ran the upgrade there. No strange behavior, no “Cancelled” status at the end, nothing weird at all, in fact. You can see a new PS session window at right here with the new 7.3.7 version clearly identified (the left-hand side shows the complete PS upgrade in Command Prompt):

Update Trick Delivers Clean PS 7.3.7 Install.split-window

Once the update is finished I used the Command Palette to open a PS session split-right, which shows the new version running.

I’ll have to remember this for future PS updates. I’ve just used this technique on a half-dozen test PCs and it works like a charm!

 

Facebooklinkedin
Facebooklinkedin

Interesting PatchMyPC Download Affects Winget

Here’s an interesting gotcha. On September 5, I wrote about uptake and intake of a new Lenovo loaner/review PC. It’s a nifty new Intel Gen13 P1 Mobile Workstation. I described using PatchMyPC to install a bunch of follow-on applications, including CrystalDiskMark. Yesterday, I figured out that an “interesting” PatchMyPC download affects winget updates thereafter. The lead-in graphic provides an important clue. Can you see it?

How an “Interesting” PatchMyPC Download Affects Winget

The output line from winget tells the story. It finds a CrystalDiskMark version (I’ll abbreviate this as CDM going forward for convenience) that differs from the one in its database. Note the line that shows version 8.0.4c installed, but 8.0.4 available. This is what causes the “unexpected error” report later in the lead-in screenshot.

As best I can interpret what’s going on is this: 8.0.4c is treated as a different version from 8.0.4. Winget doesn’t know what to do with this odd duck named 8.0.4c when it wants to install (and see) 8.0.4. Its MO is to avoid changing stuff that doesn’t match its search criteria, so the download request fails along with the update. Sigh.

Where Does PatchMyPC Come Into Play?

You’ll recall I mentioned using PatchMyPC to install a bunch of applications on the P1 Workstation in the opening paragraphs. So I fired up that program and sure enough it shows the installed (and current) version of CDM on the target PC as — you guessed it — 8.0.4c. Here’s a screencap:

Interesting PatchMyPC Download Affects Winget.pmp-versions

Note the version number for CDM (line 6 in sage green text in right column): 8.0.4c. Eureka!

So here’s how I “fixed” this non-issue. As you might expect, winget won’t uninstall this odd duck CDM version any more than it will upgrade it. So first, I used Revo Uninstall to remove the existing CDM installation.Then I ran the winget command to install CDM — namely winget install CrystalDewWorld.CystalDiskMark as shown in the following screencap. A subsequent winget upgrade command shows it no longer balks at the odd duck (and now absent) 8.0.4c version number (I had to clear an Edge update in the meantime, so the bottom line that starts “No installed package” is the one that proves CDM is no longer throwing an update notification).

Ultimately, I’m guessing this issue originates with the developer failing to provide a new winget manifest for version 8.0.4c to the winget database. That’s the explanation that best fits these observations, IMHO. And FWIW, the download also took forever to complete (more than 3 minutes for a mere 3.87 MB package). Go figure!

When winget upgrade reports “No installed package…” it means no updates are needed, including CDM. Fixed!

Of course, I had to back off the real most current version to clear this error. But that means it wasn’t really an error, doesn’t it? That’s one of the many ways I keep myself entertained, here in Windows-World!

Facebooklinkedin
Facebooklinkedin

Extra C++ Redistributable Must Go

Here’s an interesting winget puzzle. Over the past couple of days, I noticed winget was reporting success in upgrading a Visual C++ Redistributable from version 14.36.32532 to 14.38.31919.0. Yet, each time I ran winget after that the same thing would reappear. Good thing I know what’s up with that: it means the new install doesn’t remove the old, now obsolete version. Thus, that extra C++ Redistributable must go.

Accomplishing Extra C++ Redistributable Must Go

In the lead-in graphic I show the two versions side by side inside Revo (bottom of image). I used that same tool to uninstall the other one manually. If you look at the sequence of commands therein, you’ll see I check upgrades. It shows me a new Visual C++ version to install. I install it, and check again: oops! Same old version of the redistributable still needs an update.

Or does it? Actually, it needs to be uninstalled. I could’ve done it with the winget syntax:

winget uninstall Microsoft.VCRedist.2015+.x86 -v 14.36.32532.0

But instead because I had Revo already open I simply right clicked the old version, chose uninstall, and let it do its thing. Gone!

What Happened Next?

As expected, the next time I ran winget upgrade to see if any updates remained pending I got back this mysterious but welcome message. “No installed package found matching input criteria.” In winget-speak, that means it didn’t find anything that needed an update. In other words: removing the obsolete Visual C++ Redistributable took care of my previously persistent version 14.36.32532.0.

Good-oh! Glad I’ve seen this kind of thing before. It told me that I probably had to kill the old version manually, to keep it from provoking a reminder to upgrade to the new. Even though it was present already…

Facebooklinkedin
Facebooklinkedin

Using Get-WUHistory Requires Finesse

I’m a big fan of PowerShell. That’s why I was excited to learn about a collection of cmdlets from the PowerShell Gallery named PSWindowsUpdate. Chief among its constituents is a cmdlet named Get-WUHistory that I’ve been finding both helpful and vexing. I say that using Get-WUHistory requires finesse because it works well on Windows 10, but hangs on PCs with longer “history trails” in Windows 11. Let me explain and illustrate what that means…

Why Using Get-WUHistory Requires Finesse

I’m only running Windows 10 on one actual PC (not counting VMs). By chance, that’s where I started working with the PSWindowsUpdate cmdlets. To begin with, you’ll need to install this collection, using this command:

Install-Module -Name PSWindowsUpdate -Force

If you haven’t visited the PowerShell Gallery before, you’ll be asked to grant various permissions so your PC (or VM) can access and use its contents. If necessary, please do so. Then, your installation will complete. After it’s done, you can use the Get-WUHistory command (among others — see a complete list of all 25 cmdlets from this package).

There’s something going on in Windows 11 that will sometimes cause Get-WUHistory to “hang.” How can you tell? The output won’t complete, you won’t get a prompt back, and the cursor keeps blinking. Indeed, it doesn’t even respond to CTRL-C to terminate the command. You must close the open PowerShell window (or tab) to regain control over Windows Terminal.

What’s the Trick to Make Things Work?

For some odd reason limiting the scope of output keeps the Get-WUHistory cmdlet working. Thus, in Windows 11 instead of simply entering Get-WUHistory at the command line, try this version instead:

Get-WUHistory -last 1000

This tells the cmdlet to limit its output to only the first 1000 entries it finds in the update history. Notice that on one of my test PCs, the actual number of entries in the update history is only 157 items, yet the command hangs anyway — except when it’s scoped. Go figure!

Unless scoped [-last 1000] Get-WUHistory hangs on Windows 11.

The lead-in graphic shows the first screen of output from a scoped version of the Get-WUHistory cmdlet. Notice that most of the updates relate to Windows Security (Windows Defender intelligence updates, antimalware platform updates, and so forth). Too much chaff, not enough wheat, IMO. Here’s a way to turn down the volume…

Reducing Get-WUHistory Output Volume

One can, of course, filter Get-WUHistory Output — in addition to limiting its scope — to reduce the output volume. Here’s a command string I found to be incredibly helpful in seeing what’s there, sans security-related stuff:

Get-WUHistory -last 1000 |
Where-Object {$_.Title -notlike "*Security*"}

What you see broken across two lines (or more) in the preceding is actually a single (if complex) PowerShell command string. Be sure to remove or ignore any internal line breaks when running this inside Windows Terminal. You’ll get back a mercifully much shorter list of items, mostly cumulative updates (CUs), MSRTs, Update Stack Packages, and the odd antimalware platform update. As you can see, this cuts 157 items down to a more manageable 12. Good stuff!

Eliminating the word security in the “Title” field filters out most of the dross. [Click image for full-sized view.]

Facebooklinkedin
Facebooklinkedin

PowerToys Sources: WinGet & MSStore

I saw yesterday on Twitter (X?) that PowerToys version  v.0.72.0 dropped. So I started banging on WinGet to upgrade me. It’s been at least 20 hours since that announcement, but WinGet still has no manifest for the new version. Indeed, the lead-in graphic shows v.0.71.0 as current. But there are two PowerToys Sources: WinGet & MSStore. And sure enough, installing the Store version brought one of my Lenovo X380 ThinkPads up to the latest iteration. This features in the lead-in graphic as well. The second WinGet list PowerToys command shows the current version installed — with a WinGet source, no less — after I downloaded and installed the latest version from the MS Store. Go figure!

Why Two PowerToys Sources: WinGet & MSStore?

The answer to the preceding query depends on how organizations do updates internally. Those who let WU and the MS Store handle things should choose the Microsoft Store version of MS apps when they can. This will automatically handle things on its own. But those who control updates will find WinGet invaluable. It makes a great focus for automation via PowerShell scripts as and when their update windows open.

Does that mean one or the other source for updates is better? Not at all. But today, it looks like the updates through the MS Store track new releases faster than WinGet does — for PowerToys, at least. I’m also interested that even though my update comes from the store, it shows WinGet as its source. But as long as it’s updated quickly and correctly, that’s OK.

Facebooklinkedin
Facebooklinkedin