Home PowerShell Internals ISE Editor Configure ISE With PowerShell
 

Configure ISE With PowerShell

Changing ISE Settings From PowerShell

Maybe you’d like to know where the ISE editor remembers its internal settings and the list of most recently used files. Maybe you’d even like to configure the list or copy the settings to other machines.

Most options are exposed from within ISE through $PSISE.Options. Some, like the MRU list, aren’t.

Script: ISE Management Functions
Script: ISE Management Functions
ManageISE.ps1
Version: 1.0
6.2 KiB
1182 Downloads
Details...
ISE Management Functions
4.6 KiB
606 Downloads
Details...

Finding ISE Settings

Turns out ISE stores its settings in the local appdata folder. To open that folder programmatically, you could use this line:

$path = (resolve-path -Path $env:localappdata\microsoft_corporation\powershell_ise*\3.0.0.0).Path

Dir $path
explorer $path

All the settings are saved in a file called “user.config” (without file extension!) inside of that folder. Great luck that PowerShell embraces XML and makes it fairly easy to read and write to it.

Most Recently Used (MRU) Files

To see the list of your last files (MRU), try this:

$folder = (resolve-path -Path $env:localappdata\microsoft_corporation\powershell_ise*\3.0.0.0).Path
$filename = 'user.config'
$path = Join-Path -Path $folder -ChildPath $filename

[xml]$xml = Get-Content -Path $path -Raw
$MRU = $xml.SelectNodes('//setting[@name="MRU"]').Value.ArrayOfString.string
$MRU

Now, and how would you actually change the MRU list to something different? That’s a bit tricky because the XML file stores the list as an “ArrayOfString” node value. The easiest way to write changes to that node is to directly manipulate its innerXML.

This piece of code places a new file into your MRU list at position 1 and saves the changes back to the configuration file. All other items of that list remain unchanged:

$newfile = 'c:\somescript.ps1'

$folder = (resolve-path -Path $env:localappdata\microsoft_corporation\powershell_ise*\3.0.0.0).Path
$filename = 'user.config'
$path = Join-Path -Path $folder -ChildPath $filename

[xml]$xml = Get-Content -Path $path -Raw
$MRU = $xml.SelectNodes('//setting[@name="MRU"]').Value.ArrayOfString.string
$MRU[0] = $newfile
$xml.SelectNodes('//setting[@name="MRU"]').Value.ArrayOfString.InnerXML = $MRU | 
  Foreach-Object { "<string>$_</string>" } | 
  Out-String

$xml.Save($path)

Reading And Writing Other Settings

Now that we can change the MRU list, you may want to programmatically change the number of items in that list, or some other ISE settings.

Before you get carried away, always remember that from inside the ISE, you can always use $PSIse.Options to list, read and set most options. So reading and writing settings that are exposed by $PsISE.Options by directly accessing XML data is rather academic. It can be useful if you want to change the settings from outside the ISE, for example to configure a system from a script that does not run in the ISE environment. In addition, accessing raw XML settings is something you may run into for other applications or scenarios as well. So let’s have a look at what you can do.

To get to all the other settings, you can use the same approach and search for “setting” nodes like this:

$folder = (resolve-path -Path $env:localappdata\microsoft_corporation\powershell_ise*\3.0.0.0).Path
$filename = 'user.config'
$path = Join-Path -Path $folder -ChildPath $filename

[xml]$xml = Get-Content -Path $path -Raw
$xml.SelectNodes('//setting')

To read the value of a specific setting, you can wrap this into a function like Get-ISESetting.

Function Get-ISESetting
{
  param
  (
    $Name = '*'
  )

  $folder = (Resolve-Path -Path $env:localappdata\microsoft_corporation\powershell_ise*\3.0.0.0).Path
  $filename = 'user.config'
  $path = Join-Path -Path $folder -ChildPath $filename

  [xml]$xml = Get-Content -Path $path -Raw

  # find all settings available with their correct casing:
  $settings = $xml.SelectNodes('//setting') | Where-Object serializeAs -eq String | Select-Object -ExpandProperty Name
  # translate the user-submitted setting into the correct casing:
  $CorrectSettingName = $settings -like $Name

  # if no setting is found, try with wildcards
  if (!$CorrectSettingName) { $CorrectSettingName = $settings -like "*$SettingName*" }

  if ($CorrectSettingName)
  {
    $CorrectSettingName |
      Foreach-Object {
        $xml.SelectNodes(('//setting[@name="{0}"]' -f $_)) |
          Select-Object -Property Name, Value
      }
  }
  else
  {
    Write-Warning "The setting '$SettingName' does not exist. Try one of these valid settings:"
    Write-Warning ($settings -join ', ')
  }
}

It is very easy to use. Simply call it without any parameters, and you get back all settings. Call it with a setting name, and you get back the value for this specific setting. Or call it with wildcards to get back all settings that contain the keyword:

PS> Get-ISESetting mru

name                                                        value                                                      
----                                                        -----                                                      
MruCount                                                    10                                                         

PS> Get-ISESetting *window*

name                                                        value                                                      
----                                                        -----                                                      
HelpWindowHeight                                            400                                                        
HelpWindowLeft                                              -8                                                         
HelpWindowWidth                                             600                                                        
HelpWindowTop                                               -8                                                         
HelpWindowMaximized                                         True                                                       
MainWindowHeight                                            500                                                        
MainWindowTop                                               92                                                         
MainWindowMaximized                                         False                                                      
MainWindowLeft                                              26                                                         
MainWindowWidth                                             700                                                        
MainWindowHeightSetting                                     754                                                        
MainWindowWidthSetting                                      1296

Cool, eh? Get-ISESetting not only delivers the ISE settings to you. It also contains some XML tricks you may want to look at. XML is case-sensitive. Yet, you would not want the user to remember the exact casing for a setting. So in order to search for settings in a case-insensitive way, you could use XPath macros and convert everything to let’s say lower-case. However, XPath macros are not only a bit complex, they are also not supported without an XML namespace.

An easy alternative is this: first read all the settings that are present in the file, then use -like to do an case-insensitive comparison. This gets you back the keyword the user submitted – but now with the correct casing. Because -like allows wildcards, you now can also accept wildcard input.

Changing ISE Settings

Obviously, what is still missing is actually changing settings like the MruCount setting.

Again, from within the ISE and for all practical means, use $PSISE.Options.MRUCount directly!

Here is Set-ISESetting. It takes a setting at a time and assigns it a new value. So if you wanted to change the number of items in your MRU list, all you do is: Set-ISESetting -Name MRUList -Value 12. Done.

Function Set-ISESetting
{
  param
  (
    [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
    $Name = '*',

    [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
    $Value
  )

  Begin
  {
    $folder = (Resolve-Path -Path $env:localappdata\microsoft_corporation\powershell_ise*\3.0.0.0).Path
    $filename = 'user.config'
    $path = Join-Path -Path $folder -ChildPath $filename

    [xml]$xml = Get-Content -Path $path -Raw

    # find all settings available with their correct casing:
    $settings = $xml.SelectNodes('//setting') | Where-Object serializeAs -EQ String | Select-Object -ExpandProperty Name
  }

  Process
  {
    # translate the user-submitted setting into the correct casing:
    $CorrectSettingName = $settings -like $Name

    if ($CorrectSettingName)
    {
      $xml.SelectNodes(('//setting[@name="{0}"]' -f $CorrectSettingName))[0].Value = [String]$Value
    }
    else
    {
      Write-Warning "The setting '$SettingName' does not exist. Try one of these valid settings:"
      Write-Warning ($settings -join ', ')
    }
  }

  End
  {
    $xml.Save($Path)
  }
}

Complete List Of ISE-Functions

Of course, reading, writing and adding to the MRU entries should also be wrapped into functions. So I made a little script that now contains these functions:

  • Get-ISESetting: reads one or more ISE settings ($PsISE.Options may already work for you from within the ISE)
  • Set-ISESetting: sets one ISE setting and can accept pipeline input ($PsISE.Options may already work for you from within the ISE)
  • Get-ISEMRUList: dumps the current file paths from the MRU list (this you can only control via direct XML access, so it may help you)
  • Set-ISEMRUList: replaces the current MRU list with a list of new files. The parameter -Append adds fresh entries to the existing list. If the list is already full (number of entries is equal to MruCount), the list is shifted and the oldest (last) entry removed to get new room for the new entry at the beginning (same here, setting the MRU can otherwise only be done by programmatically opening files in the ISE)

So this was a nice little trip into XML county, illustrating how you can directly access software settings. It’s not the supported way, of course, and it is always better to look for an official way. And the PowerShell team has made it simple for you. For example, to clear the MRU list, you can do this:

# clear MRU list in ISE
$psISE.Options.MruCount = 0
$psISE.Options.MruCount = 12

And to add files to the MRU list, you can open them (unfortunately, you can’t close them):

$file = $psise.CurrentPowerShellTab.files.Add('c:\somepath.ps1")

All of this works only from within the ISE, but on the other hand, changes you do this way are supported. If you use the direct XML approach, then changes to the settings will have no effect on ISEs that are already running. They are read only when ISE launches. Furthermore, when ISE is closed, it will write its current settings back from memory to the config file, overwriting any changes you may have done to it.

So what you can do: configure your ISE environment from outside the ISE, for example by running the script in your classic powershell console. Or, make sure ISE gets no chance to overwrite your changes by killing it the rude way: Stop-Process -id $pid. Or, again, use $PsISE.

Have fun,

Tobias
MVP PowerShell

Script: ISE Management Functions
Script: ISE Management Functions
ManageISE.ps1
Version: 1.0
6.2 KiB
1182 Downloads
Details...
ISE Management Functions
ISE Management Functions
PTSManageISE.zip
Version: 1.0
4.6 KiB
606 Downloads
Details...