How to update a FRSM quota and template action with PowerShell

On this one, I will not go very deep with the explanation because it implies many PowerShell knowledge.
However, I will explain the main principle and give a sample of code to make your work easier if you understand it.
Most of the time, you will just have to adapt it to match your needs.

The principle

First, you have to understand how FSRM template quota objects are cascading.

  1. Templates contain one or multiple thresholds
  2. Each threshold contain one or multiple actions

Thus you have to enumerate all these objects (which are arrays) and then create them again (via new arrays) in the reverse order.

  1. Create one or more action(s)
  2. Create one or more threshold(s) with those actions as parameter
  3. Set the FSRM quota template with the thresholds as parameter

The code

Here is the code I used to change the body of emails which are sent to user reaching their quota.
Like I said you just have to adapt it in order to change any other parameter of quota templates.

Should I remember it? Don’t forget to make a backup before making any

However, you don’t break anything until you use the Set-FsrmQuotaTemplate cmdlet at line 48.
You can add the WhatIf parameter at the end of the line if you want first check which templates are impacted.

You should also think about using at line 48 the UpdateDerived parameter if, in addition of updating the template, you also want to update quotas using this template or the UpdateDerivedMatching parameter if you also want to update quotas using this template and which have not been modified since they were automatically generated.

$StringToReplace = [regex]::Escape('Please contact John DO')
$NewString = 'Please contact Jane DO'

$QuotaTemplateToUpdateList = Get-FsrmQuotaTemplate |Where-Object -FilterScript {$_.Threshold.Action.Body -match $StringToReplace}

foreach($QuotaTemplateToUpdate in $QuotaTemplateToUpdateList)
    $TresholdList = $QuotaTemplateToUpdate.Threshold

    $NewThreshHoldList = [System.Collections.ArrayList]::new($ThreshHoldList.Count)

    foreach($Threshold in $TresholdList)
        $CurrentActionList = $Threshold.Action

        $NewActionList = [System.Collections.ArrayList]::new($CurrentActionList.Count)

        foreach($Action in $CurrentActionList)

            If($Action.Type)             {$Params.'Type'             = $Action.Type}
            If($Action.MailTo)           {$Params.'MailTo'           = $Action.MailTo}
            If($Action.MailCC)           {$Params.'MailCC'           = $Action.MailCC}
            If($Action.MailBCC)          {$Params.'MailBCC'          = $Action.MailBCC}
            If($Action.Subject)          {$Params.'Subject'          = $Action.Subject}
            If($Action.Body)             {$Params.'Body'             = $Action.Body -replace $StringToReplace, $NewString}
            If($Action.EventType)        {$Params.'EventType'        = $Action.EventType}
            If($Action.Command)          {$Params.'Command'          = $Action.Command}
            If($Action.WorkingDirectory) {$Params.'WorkingDirectory' = $Action.WorkingDirectory}
            If($Action.CommandParameters){$Params.'CommandParameters'= $Action.CommandParameters}
            If($Action.SecurityLevel)    {$Params.'SecurityLevel'    = $Action.SecurityLevel}
            If($Action.KillTimeOut)      {$Params.'KillTimeOut'      = $Action.KillTimeOut}
            If($Action.ShouldLogError)   {$Params.'ShouldLogError'   = $Action.ShouldLogError}
            If($Action.ReportTypes)      {$Params.'ReportTypes'      = $Action.ReportTypes}
            If($Action.RunLimitInterval) {$Params.'RunLimitInterval' = $Action.RunLimitInterval}

            $NewAction = New-FsrmAction @Params

            $Null = $NewActionList.Add($NewAction)

        $NewThreshHold = New-FsrmQuotaThreshold -Percentage $Threshold.Percentage -Action $NewActionList

        $Null = $NewThreshHoldList.Add($NewThreshHold)

    Set-FsrmQuotaTemplate -InputObject $QuotaTemplateToUpdate -Threshold $NewThreshHoldList


It appeared in my case that the UpdateDerived parameter that I added to line 48 didn’t do anything.
Templates have been updated, but derived AutoQuotas have not.

I tried the Update-FSRM cmdlet, but this one returned an error.

Update-FsrmAutoQuota : Method "Update" not found
    + CategoryInfo          : ObjectNotFound: (MSFT_FSRMAutoQuota (Path = "H:\Home"):Root/Microsoft/...T_FSRMAutoQuota) [Update-FsrmAutoQuota], CimException
    + FullyQualifiedErrorId : HRESULT 0x80041002,Update-FsrmAutoQuota

I finished by doing it with the following command line

Get-FsrmAutoQuota | ForEach-Object -Process {Set-FsrmAutoQuota -Path $_.Path -Template $_.Template -UpdateDerived

More about

File Server Resource Manager
cmdlets (Microsoft Docs)

2 thoughts on “How to update a FRSM quota and template action with PowerShell

  1. Thank you so much for this post! It went a long way to deciphering what was happening with all these FSRM commandlets.

    I thought I’d add some small additional details that I learned from my project. In my case I am creating a quota from a template and then modifying the actions in that resulting quota. All the threshold and action work is identical.

    I was having problems with your code sample and modifying the MailCC parameter. It took me a while to realize you were filtering out null values – by putting my values in roughly the place where you had put your “replace” I was only able to replace MailCC values where one already existed. If I instead just carpet bombed and forced a MailCC parameter on every action, that was also inappropriate since not all action types support that property – the New-FsrmAction command would fail. The generic errors that FSRM provides made it difficult to debug.

    I’m also not a fan of hard-coding object fields as you did. Here’s how I modified your action section for my purposes – I hope someone finds it helpful:

                    Foreach ($Action in $Threshold.Action) { # Modify each Action in the threshold...
                        $Params=@{} # Load the parameters with copies of the old action that will be replaced...
                        Foreach ($ActionProperty in $Action.PSObject.Properties) { 
                            Switch ($ActionProperty.Name) {
                                default { If ($ActionProperty.Value) {$Params.$($ActionProperty.Name) = $ActionProperty.Value}} # Copy if not null
                                # We need to discard the problematic properties by ignoring them...
                                "PSComputerName" {}
                                "CimInstanceProperties" {}
                                "CimSystemProperties" {}
                                "CimClass" {}
                        If($Action.Type -eq "Email") { # Let's inject our target recipient... 
                             $Params.'MailCC' = ""

    $NewAction = New-FsrmAction @Params
    $Null = $NewActions.Add($NewAction)


Leave a Reply

Please log in using one of these methods to post your comment: Logo

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

Facebook photo

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

Connecting to %s