Automating the world one-liner at a time…
Unlike other tools, PowerShell ISE doesn’t have project files. Project files are a good way to set your environment up with a well known state.
Thanks to the ISE Object Model, it is possible to add some project functionality.
The script below has two main functions “Export-ISEState” and “Import-ISEState”. They can be used to save files and PowerShellTabs and reopen them later.
Even script contents for untitled files are saved.
To save the current state (state = files and PowerShellTabs), use something like:
To load the state later run:
When exporting the current state the all titled files are saved with the script from my last post. This ensures you will have the same content when importing the state later.
For untitled files, the contents are saved. When untitled files are reloaded, new untitled files are created, if their contents are not already present in some untitled file.
If you like it, you can add it to your profile (psedit $profile will edit the ISE profile) or to a module imported in your profile.
Lucio Silveira [MSFT]
Saves all ISE Files except for untitled files. If You have multiple PowerShellTabs, saves files in all tabs.
foreach($tab in $psISE.PowerShellTabs)
foreach($file in $tab.Files)
Stores the opened files in a serialized xml so that later the same set can be opened
Creates an xml file with all PowerShell tabs and file information
The name of the project to create a new version from. This will also be the name of the new project, but with a different version
Stores current state into c:\temp\files.isexml
# We are exporting a "tree" worth of information like this:
# SelectedTabDisplayName: PowerShellTab 1
# SelectedFilePath: c:\temp\a.ps1
# PowerShellTab 1:
# File 1:
# FullPath: c:\temp\a.ps1
# FileContents: $null
# File 2:
# FullPath: Untitled.ps1
# FileContents: $a=0...
# PowerShellTab 2:
# Hashtables and arraylists serialize rather well with export-clixml
# We will keep the list of PowerShellTabs in one ArrayList and the list of files
# and contents(for untitled files) inside each tab in a couple of ArrayList.
# We will use Hashtables to group the information.
# before getting file information, save all untitled files to make sure their latest
# text is on disk
foreach ($tab in $psISE.PowerShellTabs)
# $null = will avoid $files.Add from showing in the output
$null = $files.Add($file.FullPath)
# untitled files are not yet on disk so we will save the file contents inside the xml
# export-clixml performs the appropriate escaping for the contents to be inside the xml
$null = $filesContents.Add($file.Editor.Text)
# titled files get their content from disk
$null = $filesContents.Add($null)
# The DisplayName of a PowerShellTab can only be change with scripting
# we want to maintain the chosen name
# $files and $filesContents is the information gathered in the foreach $file above
# add to the list of tabs
$null = $tabs.Add($simpleTab)
# tabsToSerialize will be a hashtable with all the information we want
# it is the "root" of the information to be serialized in the hashtable we store...
# the $tabs information gathered in the foreach $tab above...
$tabToSerialize["TabInformation"] = $tabs
# ...and the selected tab and file.
$tabToSerialize["SelectedTabDisplayName"] = $psISE.CurrentPowerShellTab.DisplayName
$tabToSerialize["SelectedFilePath"] = $psISE.CurrentFile.FullPath
# now we just export it to $fileName
$tabToSerialize | export-clixml -path $fileName
Reads a file with ISE state information about which files to open and opens them
Reads a file created by Export-ISEState with the PowerShell tabs and files to open
The name of the file created with Export-ISEState
Restores current state from c:\temp\files.isexml
# currentTabs is used to keep track of the tabs currently opened.
# If "PowerShellTab 1" is opened and $fileName contains files for it, we
# want to open them in "PowerShellTab 1"
$tabs=import-cliXml -path $fileName
# those will keep track of selected tab and files
foreach ($tab in $tabs.TabInformation)
if($newTab -eq $null)
#newTab now has a brand new or a previouslly existing PowerShell tab with the same name as the one in the file
# if the tab is the selected tab save it for later selection
if($newTab.DisplayName -eq $tabs.SelectedTabDisplayName)
# currentUntitledFileContents keeps track of the contents for untitled files
# if you already have the content in one of your untitled files
# there is no reason to add the same content again
# this will make sure calling import-ISEState multiple times
# does not keep on adding untitled files
foreach ($newTabFile in $newTab.Files)
# since we will want both file and fileContents we need to use a for instead of a foreach
for($i=0;$i -lt $tab.Files.Count;$i++)
$file = $tab.Files[$i]
$fileContents = $tab.FilesContents[$i]
#fileContents will be $null for titled files
if($fileContents -eq $null)
# the overload of Add taking one string opens the file identified by the string
$newFile = $newTab.Files.Add($file)
else # the file is untitled
#see if the content is already present in $newTab
if($newFile -eq $null)
# the overload of Add taking no arguments creates a new untitled file
# The number for untitled files is determined by the application so we
# don't try to keep the untitled number, we just create a new untitled.
$newFile = $newTab.Files.Add()
# and here we restore the contents
# if the file is the selected file in the selected tab save it for later selection
if(($selectedTab -eq $newTab) -and ($tabs.SelectedFilePath -eq $file))
$selectedFile = $newFile
#finally we selected the PowerShellTab that was selected and the file that was selected on it.
if($selectedFile -ne $null)
If only it was possible to put the export into an event handler for powershell.exiting and the import into your profile. Unfortunately the asynchronous nature of eventing's powershell.exiting means that the ISE OM is often disposed and/or GC'd before the event handler can read the files collection. Sigh.
This is awesome. This functionality was one of the main reasons I was using other IDEs instead of ISE.
@Oisin G. you may not be able to reliably hook into the exiting event handler, but you can easily create another keyboard shortcut Save State And Exit, and have your profile Load State when a new PS session is started. I show how to do this in my blog post blog.danskingdom.com/powershell-ise-multiline-comment-and-uncomment-done-right-and-other-ise-gui-must-haves
I've made a feature request to have this functionality added in a later version of ISE. Go up-vote it at connect.microsoft.com/.../windows-powershell-ise-add-ability-to-save-load-session-state