RestartableSession is a PowerShell module to instantly and properly reflect the code changes to the module or script you are making. It helps you perform quick interactive testing on the console.
ScriptModuleIteration.mp4
If you have written a PowerShell module, you might have got into some situations where you had to restart the PowerShell session to reflect your code changes, such as changes to classes imported by using module
, and C# classes added by Add-Type
. It's annoying if you have to manually restart the session and import the module every time but with RestartableSession, you can make the process automatic.
This module has been tested on:
- Windows 10, Windows 11 and Ubuntu 20.04
- Windows PowerShell 5.1 and PowerShell 7.3
Warning It only runs on the ConsoleHost and does not support Windows PowerShell ISE Host or Visual Studio Code Host.
RestartableSession is available on the PowerShell Gallery. You can install the module with the following command:
Install-Module -Name RestartableSession -Scope CurrentUser
By calling Enter-RSSession
, you enter a restartable session. The specified script block is called every time the session is restarted. RS(n)
is added to the prompt to indicate that you are in a restartable session and how many times you restarted the session.
PS C:\> Enter-RSSession -OnStart {'Hello'}
Hello
RS(1) PS C:\>
Inside the restartable session, you can restart the session by calling Restart-RSSession
function.
RS(1) PS C:\> Restart-RSSession
Hello
RS(2) PS C:\>
Start-RSRestartFileWatcher
is used to automatically call Restart-RSSession
on file saves.
RS(2) PS C:\> Start-RSRestartFileWatcher -Path D:\ScriptModuleTest -IncludeSubdirectories
Finally, when you've done with the module development, you can return to the caller session by Exit-RSSession
.
RS(2) PS C:\> Exit-RSSession
PS C:\>
OnStart
script block is called at the start of an RSSession and OnEnd
script block is called at the end of the RSSession. The script blocks are called in a newly created session so if you want to pass variables of the caller session, you have to pass them through OnStartArgumentList
or OnEndArgumentList
. All the variables and functions defined in OnStart
are visible in the session because it is executed in the session scope.
PS C:\> Enter-RSSession -OnStart {$var = 99} -OnEnd {$var}
RS(1) PS C:\> $var
99
RS(1) PS C:\> Exit-RSSession
99
PS C:\>
By adding ShowProcessId
switch to Enter-RSSession
, the process ID of the restartable session is shown in the prompt which makes it easier to attach a debugger from VSCode.
PS C:\> Enter-RSSession -ShowProcessId
RS(1)[19264] PS C:\> Restart-RSSession
RS(2)[5860] PS C:\> Exit-RSSession
PS C:\>
Assuming that all the code used for the module is placed under one directory, you can set up a auto-reloading console by calling this function.
function StartScriptModuleDevelopment($ModuleDirectory)
{
$onStart = {
param($dir)
Import-Module $dir
Start-RSRestartFileWatcher -Path $dir -IncludeSubdirectories
}
Enter-RSSession -OnStart $onStart -OnStartArgumentList $ModuleDirectory -ShowProcessId
}
If the module exports classes, you need using module
statement to import the module. In order to use using module
inside a script block, you have to create the script block from a string. The video at the top of this page was made using this function.
function StartScriptClassModuleDevelopment($ModuleDirectory)
{
$scriptBlockString =
@'
using module {0}
Start-RSRestartFileWatcher -Path {0} -IncludeSubdirectories
'@
$onStart = [ScriptBlock]::Create($scriptBlockString -f $ModuleDirectory)
Enter-RSSession -OnStart $onStart -ShowProcessId
}
$OnStart
script block could be anything so you can even build a .Net project once the code has been changed and reload the dll. The session is restarted at the source code change so there is no dll blocking issue.
function StartBinaryModuleDevelopment($DotNetProjectDirectory, $DllPath)
{
$onStart = {
param($projectDir, $dll)
dotnet build $projectDir
Import-Module $dll
Start-RSRestartFileWatcher -Path $projectDir -IncludeSubdirectories
}
Enter-RSSession -OnStart $onStart -OnStartArgumentList $DotNetProjectDirectory, $DllPath -ShowProcessId
}
BinaryModuleIteration.mp4
Changelog is available here