Extending PowerShell Objects with ScriptMethods
We're in the midst of building a tool set to help me manage my MuseScore files. You should be able to apply the techniques and concepts to your work, especially if you are creating functions that write custom objects to the pipeline. When we left off, I had a function that creates a custom object from a MuseScore file.
PS Hypnos:\> Get-MuseScoreProperty
Title : Hypnos Suite
SubTitle : Nocturne for Chamber Orchestra
Composer : Jeffery D. Hicks
Copyright : (c) 2023-2025 Jeffery D. Hicks - all rights reserved
Software : MuseScore 4.4.4
Online : https://musescore.com/user/26698536/scores/13605262
CoverArt : C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\slumber.jpg
MP3 : C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\Hypnos Suite.mp3
Length : 00:12:39
Date : 3/3/2025 12:00:00 AM
Path : C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\
Duration : 00:12:39
I even extended the object to define an alias and a property set.
PS Hypnos:\> Get-MuseScoreProperty | Get-Member
TypeName: MuseScoreInfo
Name MemberType Definition
---- ---------- ----------
Duration AliasProperty Duration = Length
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Composer NoteProperty string Composer=Jeffery D. Hicks
Copyright NoteProperty string Copyright=(c) 2023-2025 Jeffery D. Hicks - all rights reserved
CoverArt NoteProperty string CoverArt=C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne...
Date NoteProperty datetime Date=3/3/2025 12:00:00 AM
Length NoteProperty System.TimeSpan Length=00:12:39
MP3 NoteProperty string MP3=C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamb...
Online NoteProperty string Online=https://musescore.com/user/26698536/scores/13605262
Path NoteProperty string ath=C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamb...
Software NoteProperty string Software=MuseScore 4.4.4
SubTitle NoteProperty string SubTitle=Nocturne for Chamber Orchestra
Title NoteProperty string Title=Hypnos Suite
RecordingData PropertySet RecordingData {Title, Subtitle, MP3, Online, Duration, CoverArt}
PS Hypnos:\> Get-MuseScoreProperty | Select RecordingData
Title : Hypnos Suite
SubTitle : Nocturne for Chamber Orchestra
MP3 : C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\Hypnos Suite.mp3
Online : https://musescore.com/user/26698536/scores/13605262
Duration : 00:12:39
CoverArt : C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\slumber.jpg
I enjoy exploring how far I can go with this process, so I decided to extend the object with several ScriptMethod
members. I've demonstrated in other articles to to create a ScriptProperty
that executes a PowerShell script block to return a value. A ScriptMethod
also executes a script block, but it performs an action with the object.
ScriptMethod
If I wanted to perform an action on multiple objects, it probably makes more sense to create a function that accepts pipeline input. However, the methods I have in mind only make sense when invoked on a single object. Yes, I could still write a function that processes a single object, but I want a reason to demonstrate creating a ScriptMethod
.
The score object includes a property with the path to the MP3 file.
PS Hypnos:\> $score = Get-MuseScoreProperty
PS Hypnos:\> $score.mp3
C:\Users\Jeff\Documents\MuseScore4\Scores\nocturne-chamber-orchestra\Hypnos Suite.mp3
Why not create a method to play the MP3 file?
Update-TypeData -TypeName MuseScoreInfo -MemberType ScriptMethod -MemberName Play -Value {
If (Test-Path $this.MP3) {
Invoke-Item $this.MP3
}
else {
Write-Warning "Can't find the MP3 file for this score."
}
} -Force
It is possible the score won't have an MP3 file so I need to test the path. If the file exists I'll use Invoke-Item
to open the file. This cmdlet will launch the default application associated with MP3 files. If the file doesn't exist, I'll write a warning message.
Don't forget that the Value
property is a script block. Use $this
to reference the current object. Using the method is a sample as this:
$score.play()