Pages

Saturday, May 28, 2016

Reset Terminal Server (RDS) Grace Period using PowerShell


Reset Terminal Services Licensing Grace Period to 120 Days
We often need to deploy Terminal Server (Remote Desktop Session Host in 2012/2016/2019) for testing purposes in development environments allowing more than 2 concurrent Remote Desktop Sessions on it. When it is installed, by default it is in default Grace licensing period which is 120 days and it works fine without specifying any TS Licensing server and Licensing Mode.

Once Grace period expires, the server does not allow even a single Remote Desktop session via RDP and all we can do is logon to the Console of machine using Physical/Virtual console depending on Physical or Virtual machines or try to get in using mstsc /admin or mstsc /console, then remove the role completely and restart the terminal server and then it starts accepting default two RDP sessions.

We sometimes find ourselves in situation when server is nearing to the end of grace period and we don’t have a TS Licensing server in place and we need the default grace period to be reset/extended to next 120 days.

I have created a Script which can be used to query the remaining days of grace period and extend/reset it to next 120 days in case needed.
 
Updated on Aug 21st 2021: 
  • Applied a Validation check if the PowerShell Console has been Launched as Administrator.
  • Updated remaining Grace Period query from  Get-WmiObject to Get-CIMInstance since Get-WmiObject no longer there in PowerShell 7
 
Updated earlier: 
  • The script has been updated with a -Force switch, If -Force switch parameter is used, It will not ask for Y/N prompt while doing the reset.
Here is how to use this script without any prompt now: 
 
.\Reset-TSGracePeriod.ps1 -Force
 
Alternatively I have also uploaded this code on My Github Repository which show the changes between old and new script.

https://github.com/Prakash82x/PowerShell/blob/master/TerminalService/Reset-TSGracePeriod.ps1


OR
 
Here goes the code.
 
 

# This Script is intended to be used for Querying remaining time and resetting Terminal Server (RDS) Grace Licensing Period to Default 120 Days.

## Developed by Prakash Kumar (prakash82x@gmail.com) May 28th 2016

## www.adminthing.blogspot.com

## Disclaimer: Please test this script in your test environment before executing on any production server.

## Author will not be responsible for any misuse/damage caused by using it.

Param(

        [Parameter(Mandatory=$false)] [Switch]$Force

     )

 

Clear-Host

$ErrorActionPreference = "SilentlyContinue"

 

## Check if PowerShell Console has been launched As Administrator

if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {

 

## Display current Status of remaining days from Grace period.

$GracePeriod = (Invoke-CimMethod -InputObject (Get-CimInstance -Namespace root/CIMV2/TerminalServices -ClassName Win32_TerminalServiceSetting) -MethodName GetGracePeriodDays).DaysLeft

Write-Host -fore Green ======================================================

Write-Host -fore Green 'Terminal Server (RDS) grace period Days remaining are' : $GracePeriod

Write-Host -fore Green ====================================================== 

Write-Host

 

## Check if -Force Parameter has been used, If so, It will not prompt for Y/N while executing the script and will simply reset the Grace Period.

If (-not $Force)

{

$Response = Read-Host "Do you want to reset Terminal Server (RDS) Grace period to Default 120 Days ? (Y/N)"

}

 

if ($Response -eq "Y" -or $Force) {

## Reset Terminal Services Grace period to 120 Days

 

$definition = @"

using System;

using System.Runtime.InteropServices;

namespace Win32Api

{

       public class NtDll

       {

             [DllImport("ntdll.dll", EntryPoint="RtlAdjustPrivilege")]

             public static extern int RtlAdjustPrivilege(ulong Privilege, bool Enable, bool CurrentThread, ref bool Enabled);

       }

}

"@

 

Add-Type -TypeDefinition $definition -PassThru

 

$bEnabled = $false

 

## Enable SeTakeOwnershipPrivilege

$res = [Win32Api.NtDll]::RtlAdjustPrivilege(9, $true, $false, [ref]$bEnabled)

 

## Take Ownership on the Key

$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Control\Terminal Server\RCM\GracePeriod", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership)

$acl = $key.GetAccessControl()

$acl.SetOwner([System.Security.Principal.NTAccount]"Administrators")

$key.SetAccessControl($acl)

 

## Assign Full Controll permissions to Administrators on the key.

$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("Administrators","FullControl","Allow")

$acl.SetAccessRule($rule)

$key.SetAccessControl($acl)

 

## Finally Delete the key which resets the Grace Period counter to 120 Days.

Remove-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\RCM\GracePeriod'

 

write-host

Write-host -ForegroundColor Red 'Resetting, Please Wait....'

Start-Sleep -Seconds 10

 

}

 

Else

    {

Write-Host

Write-Host -ForegroundColor Yellow '**You Chose not to reset Grace period of Terminal Server (RDS) Licensing'

  }

 

## Display Remaining Days again as final status

tlsbln.exe

$GracePost = (Invoke-CimMethod -InputObject (Get-CimInstance -Namespace root/CIMV2/TerminalServices -ClassName Win32_TerminalServiceSetting) -MethodName GetGracePeriodDays).DaysLeft

Write-Host

Write-Host -fore Yellow =====================================================

Write-Host -fore Yellow 'Terminal Server (RDS) grace period Days remaining are' : $GracePost

Write-Host -fore Yellow =====================================================

 

if ($Response -eq "Y" -or $Force)

        {

            Write-Host -Fore Cyan `n"IMPORTANT: Please make sure you restart following services manually to bring this reset in effect:`n`n* Remote Desktop Configuration Properties `n* Remote Desktop Services"

        }

}

Else

{

    Write-Host -fore RED =====================================================

    Write-host -ForegroundColor RED *`0`0`0`0 Please Launch PowerShell as Administrator `0`0`0`0*

    Write-Host -fore RED =====================================================

}

## Cleanup of Variables

Remove-Variable * -ErrorAction SilentlyContinue

 



##End of Code##

Note: You will have to restart following services for the reset to come into effect.

  • Remote Desktop Configuration Properties
  • Remote Desktop Services
 
As soon as these services are restarted all the active sessions will be disconnected (Not logged off), Wait for a minute and reconnect again.

Please post in comments below if you think it can be improved.
 

43 comments:

  1. Can you update this script to run on a Win2012 R2 install? Also, if a chose not to reset the grace period it doesn't display the remaining days, on a 2012 R2.

    Thank you,
    Adrian

    ReplyDelete
  2. Well it should work on 2012 R2 as well but in case it does not you can try following options to check the same:

    1. Run CMD as Administrator and try this:
    wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TerminalServiceSetting WHERE (__CLASS !="")


    2. Run CMD as Administrator and try this it shows a balloon tip in the system tray showing remaining days.
    tlsbln

    ReplyDelete
  3. Hi,

    I m using windows 2016 server, i cant possible to delete key in grace period inside please helpme.
    "Access Denied " Message shows

    ReplyDelete
    Replies
    1. Check that the local account you are using to log in is enabled and not set to force a password change on the next log-in. I was having the same issue, and changing my local Administrator's account settings to "Password Never Expires" fixed this for me.

      Delete
  4. Start: Windows PowerShell ISE as administrator.
    Then, Open the PS-Script and run it.
    Answer: Y and wait a few. Done :)

    ReplyDelete
  5. Worked flawlessly on my 2012 R2 server, which is having problems with licensing. Thank you for this useful tool.

    ReplyDelete
  6. Thankyou so much. Worked fine on our 2012 R2.

    ReplyDelete
  7. FYI - Even running ISE as admin, I had to change permissions at Grace Period in the registry key to allow deletion. Gave Full to Administrators (this apparently changed, as it had worked fine previously, not sure if it was MS or security in IT). This has been a really useful script, thanks!

    ReplyDelete
  8. This script (Reset Terminal Server (RDS) Grace Period using PowerShell) was posted on Microsoft Technet script repository which has been taken down by Microsoft it seems and it is no longer available there.
    dead link https://gallery.technet.microsoft.com/scriptcenter/Reset-Terminal-Server-RDS-44922d91)

    ReplyDelete
  9. Thank you Prakash. Worked on 2016.

    ReplyDelete
  10. Hi Prakash, does it work for a 2019 Standard?

    ReplyDelete
    Replies
    1. Well, though I have not tested it yet on 2019 but It should work. Please give it a try and let me know if it does not.

      Delete
    2. Work correctly with 2019 Standard

      Delete
  11. This comment has been removed by the author.

    ReplyDelete
  12. This patch is useful to optionally execute with parameter Y (execution without confirmation)

    ===================
    $param1=$args[0]

    Clear-Host
    $ErrorActionPreference = "SilentlyContinue"

    ## Display current Status of remaining days from Grace period.
    $GracePeriod = (Invoke-WmiMethod -PATH (gwmi -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).__PATH -name GetGracePeriodDays).daysleft
    Write-Host -fore Green ======================================================
    Write-Host -fore Green 'Terminal Server (RDS) grace period Days remaining are' : $GracePeriod
    Write-Host -fore Green ======================================================
    Write-Host

    if ($param1 -ne "Y") {
    $Response = Read-Host "Do you want to reset Terminal Server (RDS) Grace period to Default 120 Days ? (Y/N)"
    } else {
    $Response = "Y"
    }

    [..]
    ===================

    ReplyDelete
    Replies
    1. I didnt get it to work but if you change:

      if ($param1 -ne "Y") {
      to
      if ($param1 -eq "Y") {

      this is what I use:
      --------------------
      ## This Script is intended to be used for Querying remaining time and resetting Terminal Server (RDS) Grace Licensing Period to Default 120 Days.
      ## Developed by Prakash Kumar (prakash82x@gmail.com) May 28th 2016
      ## www.adminthing.blogspot.com
      ## Disclaimer: Please test this script in your test environment before executing on any production server.
      ## Author will not be responsible for any misuse/damage caused by using it.

      $param1=$args[0]

      Clear-Host
      $ErrorActionPreference = "SilentlyContinue"

      ## Display current Status of remaining days from Grace period.
      $GracePeriod = (Invoke-WmiMethod -PATH (gwmi -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).__PATH -name GetGracePeriodDays).daysleft
      Write-Host -fore Green ======================================================
      Write-Host -fore Green 'Terminal Server (RDS) grace period Days remaining are' : $GracePeriod
      Write-Host -fore Green ======================================================
      Write-Host

      if ($param1 -eq "Y") {
      $Response = Read-Host "Do you want to reset Terminal Server (RDS) Grace period to Default 120 Days ? (Y/N)"
      } else {
      $Response = "Y"
      }

      if ($Response -eq "Y") {
      ## Reset Terminal Services Grace period to 120 Days

      $definition = @"
      using System;
      using System.Runtime.InteropServices;
      namespace Win32Api
      {
      public class NtDll
      {
      [DllImport("ntdll.dll", EntryPoint="RtlAdjustPrivilege")]
      public static extern int RtlAdjustPrivilege(ulong Privilege, bool Enable, bool CurrentThread, ref bool Enabled);
      }
      }
      "@

      Add-Type -TypeDefinition $definition -PassThru

      $bEnabled = $false

      ## Enable SeTakeOwnershipPrivilege
      $res = [Win32Api.NtDll]::RtlAdjustPrivilege(9, $true, $false, [ref]$bEnabled)

      ## Take Ownership on the Key
      $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Control\Terminal Server\RCM\GracePeriod", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership)
      $acl = $key.GetAccessControl()
      $acl.SetOwner([System.Security.Principal.NTAccount]"Administrators")
      $key.SetAccessControl($acl)

      ## Assign Full Controll permissions to Administrators on the key.
      $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("Administrators","FullControl","Allow")
      $acl.SetAccessRule($rule)
      $key.SetAccessControl($acl)

      ## Finally Delete the key which resets the Grace Period counter to 120 Days.
      Remove-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\RCM\GracePeriod'

      write-host
      Write-host -ForegroundColor Red 'Resetting, Please Wait....'
      Start-Sleep -Seconds 10

      }

      Else
      {
      Write-Host
      Write-Host -ForegroundColor Yellow '**You Chose not to reset Grace period of Terminal Server (RDS) Licensing'
      }

      ## Display Remaining Days again as final status
      tlsbln.exe
      $GracePost = (Invoke-WmiMethod -PATH (gwmi -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).__PATH -name GetGracePeriodDays).daysleft
      Write-Host
      Write-Host -fore Yellow =====================================================
      Write-Host -fore Yellow 'Terminal Server (RDS) grace period Days remaining are' : $GracePost
      Write-Host -fore Yellow =====================================================

      ## Cleanup of Variables
      Remove-Variable * -ErrorAction SilentlyContinue

      Delete
  13. Hi!
    Thanks so much!
    Also works on windows Server 2019!

    ReplyDelete
  14. Does resetting the grace period to 120 days ever stop working in windows 2016? It seems that it has for me

    ReplyDelete
    Replies
    1. Nope, It should work on 2016, Have used it so many times. Could you post the error that you are getting ?

      Delete
    2. Not working here, unfortunetely.

      Delete
    3. when you say its not working.. Can you post the error (if any) maybe I can take a look at it ?
      I have never seen any issues with it so far.

      Delete
  15. Hi Prakaash. I just tried running the script via PowerShell ISE in Windows Server 2019. It states "Reset-TSGracePeriod.ps1 is not digitally signed. You cannot run this script on the current system". What would I need to do?

    ReplyDelete
    Replies
    1. Tts complaining because of the PowerShell Execution Policy set on your machine.
      Please try running following command on the PowerShell console (don't forget to run as Administrator) and then retry executing the script.

      Set-ExecutionPolicy -Scope CurrentUser Unrestricted

      Delete
  16. This comment has been removed by the author.

    ReplyDelete
  17. I work Grade on windows 2016, Thx...

    ReplyDelete
  18. Hello,
    I tried the script on Windows 2012 R2 Datacenter edition, sript says it is done, but nothing happens, The message about configuration of licensing server still appears even after restart of RDS services.
    ISPublic = True, IsSerial=False Name=NtD11, BaseType=System.Object

    Any suggestions please?

    ReplyDelete
    Replies
    1. Sorry, it was probably due to fact i have tried this under domain admin account not local admin on the server... so it works

      Delete
  19. Please note the Administrators group is not necessarilly called Admnistrators, depending on the language seting of the local system. It might be better to go by the SID.

    ReplyDelete
    Replies
    1. That's a fair point. I will see if I can do something to make necessary modifications and enable it to run with other language settings too. Considering my knowledge with other languages than English it would not be that easy for me :)

      Delete
  20. It didn't work for me.

    I run in cmd as an administrator and it throws:

    C:\Users\raul\Documents\RDP>.\ResetRDP120d.bat -Force

    C:\Users\raul\Documents\RDP>## This Script is intended to be used for Queryin
    g remaining time and resetting Terminal Server (RDS) Grace Licensing Period to D
    efault 120 Days.
    '##' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>## Developed by Prakash Kumar (prakash82x@gmail.c
    om) May 28th 2016
    '##' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>## www.adminthing.blogspot.com
    '##' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>## Disclaimer: Please test this script in your te
    st environment before executing on any production server.
    '##' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>## Author will not be responsible for any misuse/
    damage caused by using it.
    '##' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>Param(
    'Param' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>[Parameter(Mandatory=$false)] [Switch]$Force
    '[Parameter' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>Clear-Host
    'Clear-Host' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>$ErrorActionPreference = "SilentlyContinue"
    '$ErrorActionPreference' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>## Display current Status of remaining days from
    Grace period.
    '##' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>$GracePeriod = (Invoke-WmiMethod -PATH (gwmi -nam
    espace root\cimv2\terminalservices -class win32_terminalservicesetting).__PATH -
    name GetGracePeriodDays).daysleft
    '$GracePeriod' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>Write-Host -fore Green ==========================
    ============================
    'Write-Host' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>Write-Host -fore Green 'Terminal Server (RDS) gra
    ce period Days remaining are' : $GracePeriod
    'Write-Host' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>Write-Host -fore Green ==========================
    ============================
    'Write-Host' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>Write-Host
    'Write-Host' is not recognized as an internal or external command,
    operable program or batch file.

    C:\Users\raul\Documents\RDP>## Check if -Force Parameter has been used, If so
    , It will not prompt for Y/N while executing the script and will simply reset th
    e Grace Period.
    '##' is not recognized as an internal or external command,
    operable program or batch file.

    ReplyDelete
  21. Hello, Prakash Kumar! Thanks for the awesome article! Could you be so kind to recommend some RDS where we are able to use this trick?

    ReplyDelete
  22. Can’t seem to get the script to reset the expired license, Ran it in admin with control of the hkey and the license stays expired after reboot every time... need help

    ReplyDelete
  23. This comment has been removed by the author.

    ReplyDelete
  24. If different language (so not english verion of windows server 2016/2019) must change the "administrators" to local language. In Hungarian windows "Administrators" = "Rendszergazdák"
    Then work it.

    ReplyDelete
    Replies
    1. Hey!! thanks for pointing out. I will check this and try to update the code.

      Delete
  25. I cannot get the $GracePeriod variable to work
    $GracePeriod = (Invoke-WmiMethod -PATH (gwmi -namespace root\cimv2\terminalservices -class win32_terminalservicesetting).__PATH -name GetGracePeriodDays).daysleft

    When I execute this in an extra Powershell Sciptit says:

    Invoke-WmiMethod :
    At line:1 char:17
    + ... cePeriod = (Invoke-WmiMethod -PATH (gwmi -namespace root\cimv2\termin ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Invoke-WmiMethod], FileNotFoundException
    + FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerShell.Commands.InvokeWmiMethod

    And in your script ther is no output at this point:

    Terminal Server (RDS) grace period Days remaining are :

    ReplyDelete
    Replies
    1. Hey Marc,
      I suspect that it is throwing error because you are using PowerShell 7 and my script uses the cmdlet Get-WmiObject to fetch the remaining Grace Period Days.
      I will soon be updating the script with a fix to that and post that it should be working just fine.

      Delete
    2. Hey Marc, I got some time and have updated the Script with following enhancements:
      * Validation while executing it to check if PowerShell has been launched as Administrator.
      * Replaced the Remaining Grace Period days to work with PowerShell 7 as well which lacks Get-WmiObject cmdlets.

      Delete
  26. Time saving script, Guys you can create task to run it automatically.

    ReplyDelete
  27. Hi Prakash.
    i used your script to reset GracePeriod. but after the execution the RDP connection does just not open anymore.
    i tries to open the connection and instantly closes again. any idea why that is?
    (before the reset it just gave me the "GracePeriod expired" message)

    Greetings Mario

    ReplyDelete
    Replies
    1. PS: the PS command which returns the "Daysleft" of "GetGracePeriodDays" returned "0" before the reset script execution and after that Powershell now fails to return the value for "Daysleft" with an error message.
      the registry key "...\RCM\GracePeriod" is now completely missing though (it existed b4) - is that intended?

      Delete
  28. I appreciate you providing this information. I have found it extremely interesting. The information you provide is valuable to me. Your efforts are much appreciated. My experience with this information has been highly beneficial to me, and I hope that it will be equally beneficial to others. how long is grace period

    ReplyDelete