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:
Export-ISEState c:\temp\files.isexml
To load the state later run:
Import-ISEState c:\temp\files.isexml
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]
function Save-AllISEFiles
{
<#
.SYNOPSIS
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)
{
if(!$file.IsUntitled)
{
$file.Save()
}
}
}
}
function Export-ISEState
{
<#
.SYNOPSIS
Stores the opened files in a serialized xml so that later the same set can be opened
.DESCRIPTION
Creates an xml file with all PowerShell tabs and file information
.PARAMETER fileName
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
.EXAMPLE
Stores current state into c:\temp\files.isexml
Export-ISEState c:\temp\files.isexml
#>
Param
(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$fileName
)
# We are exporting a “tree” worth of information like this:
#
# SelectedTabDisplayName: PowerShellTab 1
# SelectedFilePath: c:\temp\a.ps1
# TabInformation:
# 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.
$tabs=new-object collections.arraylist
# before getting file information, save all untitled files to make sure their latest
# text is on disk
Save-AllISEFiles
foreach ($tab in $psISE.PowerShellTabs)
{
$files=new-object collections.arraylist
$filesContents=new-object collections.arraylist
foreach($file in $tab.Files)
{
# $null = will avoid $files.Add from showing in the output
$null = $files.Add($file.FullPath)
if($file.IsUntitled)
{
# 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)
}
else
{
# titled files get their content from disk
$null = $filesContents.Add($null)
}
}
$simpleTab=new-object collections.hashtable
# The DisplayName of a PowerShellTab can only be change with scripting
# we want to maintain the chosen name
$simpleTab[“DisplayName”]=$tab.DisplayName
# $files and $filesContents is the information gathered in the foreach $file above
$simpleTab[“Files”]=$files
$simpleTab[“FilesContents”]=$filesContents
# 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…
$tabToSerialize=new-object collections.hashtable
# 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
}
function Import-ISEState
{
<#
.SYNOPSIS
Reads a file with ISE state information about which files to open and opens them
.DESCRIPTION
Reads a file created by Export-ISEState with the PowerShell tabs and files to open
.PARAMETER fileName
The name of the file created with Export-ISEState
.EXAMPLE
Restores current state from c:\temp\files.isexml
Import-ISEState c:\temp\files.isexml
#>
Param
(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$fileName
)
# 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”
$currentTabs=new-object collections.hashtable
foreach ($tab in $psISE.PowerShellTabs)
{
$currentTabs[$tab.DisplayName]=$tab
}
$tabs=import-cliXml -path $fileName
# those will keep track of selected tab and files
$selectedTab=$null
$selectedFile=$null
foreach ($tab in $tabs.TabInformation)
{
$newTab=$currentTabs[$tab.DisplayName]
if($newTab -eq $null)
{
$newTab=$psISE.PowerShellTabs.Add()
$newTab.DisplayName=$tab.DisplayName
}
#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)
{
$selectedTab=$newTab
}
# 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
$currentUntitledFileContents=new-object collections.hashtable
foreach ($newTabFile in $newTab.Files)
{
if($newTabFile.IsUntitled)
{
$currentUntitledFileContents[$newTabFile.Editor.Text]=$newTabFile
}
}
# 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
$newFile=$currentUntitledFileContents[$fileContents]
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
$newFile.Editor.Text=$fileContents
}
}
# 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.
$psISE.PowerShellTabs.SetSelectedPowerShellTab($selectedTab)
if($selectedFile -ne $null)
{
$selectedTab.Files.SetSelectedFile($selectedFile)
}
}
0 comments