Tooling Around with PowerShell
It is a brand new month which means a lot of new content heading your way. Before we get to that, I have a few housekeeping items. First, as I mentioned in the last email, if you need to manage your subscription use the links in the email footer. You might want to keep at least one email so that you have the links should you need them.
Behind the PowerShell Pipeline - The Book
In case you missed my announcements, I have finished and published my latest book, Behind the PowerShell Pipeline. The book is published on Leanpub which means once you own a copy you get future updates for free. This is only available in an eBook format. You can get a PDF or EPUB version. I don't have any immediate plans for a print version or making the title available on Amazon. You might be interested in the launch video I did on YouTube. You can also get the book in a bundle with the PowerShell Scripting and Toolmaking book.
Even though the content of the book is drawn from this newsletter, I've refreshed and extended many chapters.
Custom Formatting for RTPSUG
I know this is last minute notice, but I am talking to the Research Triangle Park PowerShell User Group this Wednesday, March 5th at 8:00PM Eastern Time. You can join the meeting virtually. Register at https://www.meetup.com/research-triangle-powershell-users-group/events/306393470
2025 PowerShell Community Awards
Finally, at last year's PowerShell Summit, they announced the inaugural winners of a trio of community awards. Last year's winners were selected by the DevOps Collective Board of Advisors. This year, nominations are open to the community. You do not need to attend the Summit to nominate someone. Go to https://survey.sogolytics.com/r/Iwcr48 before 3 April, 2025 to nominate. There are three awards. This is your opportunity to contribute, even in a small way, to the PowerShell community.
MuseScore Info
Alright, let's dive in. As some of you may know, in my free time I dabble in music composition. I post my scores online at MuseScore.com. To create my compositions, I use the MuseScore open source project on my Windows 11 desktop. The software not only lets me publish online, but I can also create PDFs and MP3s of my scores. I recently had a need to update the MP3 files with tag information so I could publish them on my NAS for home use. Naturally, I turned to PowerShell to help me with this task. One thing led to another, and I ended with a few PowerShell functions. I know the use-case is very specific, but the techniques I used might be helpful to you in other scenarios. You should always be on the lookout for snippets and tips that you can use in your own projects.
Each composition is stored in a folder with the associated files.
PS Hypnos:\> dir
Directory: C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 3/3/2025 2:42 PM references
-a--- 3/3/2025 2:45 PM 12139205 Hypnos Suite.mp3
-a--- 3/3/2025 2:42 PM 937984 Hypnos Suite.mscz
-a--- 3/3/2025 2:43 PM 127697 Hypnos Suite.mxl
-a--- 3/3/2025 2:43 PM 1140670 Hypnos Suite.pdf
-a--- 5/29/2024 5:05 PM 1259 notes.txt
-a--- 11/18/2023 2:39 PM 102291 slumber.jpg
I'm using a PSDrive to save space at my prompt. You can see the actual path in the output. The mscz
file is the MuseScore data file. The jpg
file is used as th cover image for the score.

I eventually want to use this image as the cover art for the MP3 file. I also want to update the ID3 tags with the title, composer, and year. I could do this manually, but where is the fun in that? I decided to write a PowerShell function to do this for me.
The other file that will come into play is the mxl
file. This is a compressed version of the MuseScore data file in XML format. I can extract information about the score from this file using PowerShell. My intention is to extract score information and update the MP3 file with the appropriate tags.
I'll begin with defining a variable for the path to MuseScore folder.
PS Hypnos:\> $Path = "."
Note that I am using a PSDrive and a relative path. There's nothing inherently wrong with this, but to avoid problems, I'm going to convert the path to a full filesystem path.
PS Hypnos:\> $Path = Convert-Path $Path
PS Hypnos:\> $Path
C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\
Next, I need to get the mxl
file. I am assuming there will be only one such file in the folder.
PS Hypnos:\> $mxl = Get-ChildItem -Path $Path -Filter *.mxl
PS Hypnos:\> $mxl.fullName
C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\Hypnos Suite.mxl
This file is actually a ZIP archive with a different file extension. I can use the Expand-Archive
cmdlet to extract the contents. I'll define a target folder in my TEMP directory, using the mxl
file base name as part of the path.
$ZipDestination = Join-Path -Path $env:TEMP -ChildPath $mxl.BaseName
I always find it better to use Join-Path
to build paths and not attempt to concatenate strings. I can use this destination path with Expand-Archive
.
PS C:\> Expand-Archive -Path $mxl.FullName -DestinationPath $ZipDestination -Force
PS Hypnos:\> dir $ZipDestination
Directory: C:\Users\Jeff\AppData\Local\Temp\Hypnos Suite
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 3/3/2025 3:02 PM META-INF
-a--- 3/3/2025 2:43 PM 3098691 score.xml
And just like that, I have an XML file to work with. It is easy enough to turn this into an XML document.
[xml]$score = Get-Content $ZipDestination\*.xml
> Even though the XML file will most likely be called score.xml
, during development and testing, I discovered that in older MuseScore versions, this file may have other names so I'll use a wildcard to get the file.