Class in PowerShell 5 that run custom code when you "set" property

Tagged: ,

This topic contains 4 replies, has 4 voices, and was last updated by Profile photo of Bor Bor 7 months, 3 weeks ago.

  • Author
    Posts
  • #37909
    Profile photo of Bor
    Bor
    Participant

    Hi,

    It took me some time to find a way how to use classes in something else then DSC resource…

    I would like to build class (and advanced function that returns this class) that has a few properties that by default have data from specified registry values. Object from this class may look like for example like this:

    $mySpecial = [MySpecial]::new()
    $mySpecial | gm
    
    
       TypeName: MySpecial
    
    Name        MemberType Definition                    
    ----        ---------- ----------                    
    ...             
    Prop0       Property   string Prop0 {get;set;}       
    Prop1       Property   string Prop1 {get;set;}       
    Prop2       Property   string Prop2 {get;set;}  
    

    When I create an object from this class then I will be able to run for example:
    $mySpecial.Prop0
    and I will get data from specified registry value.

    But the main reason why I want to use classes is to be able to run
    $mySpecial.Prop0 = 'Something else'
    and modify data in registry. But I have no idea how to implement class with custom code when I "set" property. Please can you give me some examples?

    Other option is to implement SetProp0() method but I believe that this is not the right way how to do it.

    Thank you for any help,
    Bor

  • #37922
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Hi Bor,
    Here is a very simplified example reading a text file for input and writing back to the text file when setting the property. Of course this is a public property so left just like this, the underlying code would be exposed to everyone. This should, however, give you somewhere to start.

    Class AppDB {
        AppDB(){
            $prop = new-object management.automation.PsScriptProperty 'connectionstring',{Get-Content c:\temp\out.txt},{param($newvalue) $newvalue | Out-File c:\temp\out.txt}
            $this.psobject.properties.add($prop)
        }
    }
    
  • #37925
    Profile photo of Christian Sandfeld
    Christian Sandfeld
    Participant

    If you have an hour or two, try taking a look at June Blenders "A Class of Wine" talk (from Virtual PowerShell User Group):

    Gives a pretty good understanding of how to work with classes.

  • #37926
    Profile photo of Rudolf Vesely
    Rudolf Vesely
    Participant

    Basically what you need is to use get and set accessors. I have just tried it like I would do it in C# but it doesn't work. Looks like PowerShell doesn't accept script block for [int] property.

    class MyDate {
        hidden [int] $_month = 3
        
        [int] $Month {
            get {
                return $_month
            }
            set {
                if ($value -gt 0 -and $value -lt 13) {
                    $this._month = $value
                } else {
                    Write-Warning -Message 'wrong number'
                }
            }
        }
        
        [void] DoSomething() {
            Write-Warning -Message 'Hello World'
        }
        hidden [void] doNotShowThisMethod() {
            Write-Warning -Message 'Hello World'
        }
    }
    
    $myDate = [MyDate]::new()
    $myDate | Get-Member
    
  • #37967
    Profile photo of Bor
    Bor
    Participant

    @Curtis: Thank you. Do you know about different ways? I would prefer not using PsScriptProperty since I would prefer using more native way...

    @Rudolf: Thank you. Unfortunately as you mentioned, this way works only in C#.

    @Christian: I saw the video from User Group, thank you. If I understand correctly It might be possible to edit set_NameOfProperty() / get_NameOfProperty() methods that are autogenerated by PowerShell. This is probably the only way how to accomplish my goal without using PsScriptProperty.

You must be logged in to reply to this topic.