Quick Hits: Writing to a Read-Only Property

This post is less on doing something useful and more on just proving that I can do something even though PowerShell is trying to tell me that I cannot do it. That little thing is updating a property on an object that is set as Read-Only.

My example to show you how you can do something like this is by looking at $PSVersionTable which as we all know gives us some great information about what version of PowerShell that we are using.

$PSVersionTable

image

I am also using this as this was an example used in our previous user group meeting in which we were shown that the properties here could not be updated.

From this object, I am going to look more at the PSVersion property which of course is an object within this object.

$PSVersionTable.PSVersion

image

Looking at the properties of this object, we can see that each of the properties are shown as Read-Only by only having the Get method available to use.

$PSVersionTable.PSVersion | Get-Member

image

Furthermore, I am greeted with a nice error stating that my attempts to modify this have been foolish and that I should just give up.

$PSVersionTable.PSVersion.Major = 10

image

Yea, I guess I could just throw in the towel and move onto something more useful like updating some bugs on a module, but I think that I can do better here! And by using some reflection magic, I can make this happen!

To do this, I need to look at the hidden fields for the PSVersion object.

$PSVersionTable.PSVersion.GetType().GetFields('static,nonpublic,instance').Name

image

Here we can see that the field that we need to look at updating is _Major.  Now we need to figure out how we can set this.

$Field = $PSVersionTable.PSVersion.GetType().GetField('_Major','static,nonpublic,instance')
$Field | Get-Member

SNAGHTML32a4c8

Looking at the methods, I see a SetValue that accepts a object and a value for the object. This seems pretty simple,right? Just call the method and update the value.

$Field.SetValue($PSVersionTable.PSVersion,10)
$PSVersionTable.PSVersion

SNAGHTML59e81d

Perfect! We have now updated this “Read-Only” property to give us PowerShell V10! Now this will go away once we close and re-open PowerShell but it still a fun thing to do to show off how you can update these kinds of values.

About Boe Prox

Microsoft Cloud and Datacenter MVP working as a SQL DBA.
This entry was posted in powershell and tagged , , , . Bookmark the permalink.

4 Responses to Quick Hits: Writing to a Read-Only Property

  1. Dan Clark says:

    Used this today for mocking purposes. Thank you!

  2. Pingback: Quick Hits: Writing to a Read-Only Property - How to Code .NET

  3. mdedeboer says:

    Love it! Do you have suggestions on how to discover the available methods?

    For this specific example:
    GetType().GetFields(‘static,nonpublic,instance’).Name

    I was able to discover GetType().GetFields() with Get-Member easily enough.
    $PSVersionTable.GetType().GetFields shows the overload definitions:

    OverloadDefinitions

    System.Reflection.FieldInfo[] GetFields()
    System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr)
    System.Reflection.FieldInfo[] _Type.GetFields(System.Reflection.BindingFlags bindingAttr)
    System.Reflection.FieldInfo[] _Type.GetFields()
    System.Reflection.FieldInfo[] IReflect.GetFields(System.Reflection.BindingFlags bindingAttr)

    Checking MSDN I found the definition:
    https://msdn.microsoft.com/en-us/library/6ztex2dc(v=vs.110).aspx

    This explains the static,nonpublic portion however according to the article you must specify either Instance or Static….however you have specified both. From my testing it appears that you can specify both with no issue.

    Is this a pretty standard method for discovering methods used with reflection, or is there a cleaner way to discover this?

    Thanks!

    Matthew

    • Boe Prox says:

      I think I specify both instance and static because there is a difference in the number of items that are returned. My methods example below is a good example of that.

      For finding methods, the approach would be the same but instead you are using GetMethods() instead. Take this example below to see what happens:

      [string].GetMethods('nonpublic,static,instance').Name
      

      Here you will see all of the available methods for the [string] type.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s